From f32f1f35d21e14b4591f647f5b3ec7c2ee7d7cd9 Mon Sep 17 00:00:00 2001 From: Shane K Moore <41407272+shane-moore@users.noreply.github.com> Date: Mon, 25 Sep 2023 18:10:21 -0700 Subject: [PATCH 1/6] chore: ibc tokens script --- .../src/client/wasm/nameservice/utils.ts | 2 + packages/sdk-ui-ts/package.json | 5 +- .../sdk-ui-ts/src/denom/DenomClientAsync.ts | 27 +- .../src/services/ibc/ibcTokenMetadata.json | 812 ++++++++++++++++++ packages/sdk-ui-ts/src/services/ibc/tokens.ts | 62 ++ 5 files changed, 904 insertions(+), 4 deletions(-) create mode 100644 packages/sdk-ui-ts/src/services/ibc/ibcTokenMetadata.json create mode 100644 packages/sdk-ui-ts/src/services/ibc/tokens.ts diff --git a/packages/sdk-ts/src/client/wasm/nameservice/utils.ts b/packages/sdk-ts/src/client/wasm/nameservice/utils.ts index 2ab1a0784..387ca8dc7 100644 --- a/packages/sdk-ts/src/client/wasm/nameservice/utils.ts +++ b/packages/sdk-ts/src/client/wasm/nameservice/utils.ts @@ -28,7 +28,9 @@ const nameToNode = (name: string) => { if (!name) { return [] } + const hash = nameHash(name) + return Array.from(Buffer.from(hash.slice(2), 'hex')) } diff --git a/packages/sdk-ui-ts/package.json b/packages/sdk-ui-ts/package.json index bd5f16990..4be920a23 100644 --- a/packages/sdk-ui-ts/package.json +++ b/packages/sdk-ui-ts/package.json @@ -18,7 +18,7 @@ }, "scripts": { "postinstall": "link-module-alias", - "build": "tsc --build tsconfig.build.json && tsc --build tsconfig.build.esm.json && yarn build:post && link-module-alias && yarn copy-files", + "build": "tsc --build tsconfig.build.json && tsc --build tsconfig.build.esm.json && yarn build:post && link-module-alias && yarn copy-files && yarn get-ibc-tokens", "build:watch": "tsc --build -w tsconfig.build.json && tsc -w --build tsconfig.build.esm.json && yarn build:post && link-module-alias", "build:post": "shx cp ../../etc/stub/package.json.stub dist/cjs/package.json && shx cp ../../etc/stub/package.esm.json.stub dist/esm/package.json", "clean": "tsc --build tsconfig.build.json --clean && tsc --build tsconfig.build.esm.json --clean && shx rm -rf coverage *.log junit.xml dist && jest --clearCache && shx mkdir -p dist", @@ -31,7 +31,8 @@ "dev": "ts-node-dev -r tsconfig-paths/register src/index.ts", "start": "node dist/index.js", "validators-logo": "ts-node-dev --ignore-watch=validators-logo ./src/validators-logo && yarn copy-files", - "validators-logo:update-all": "ts-node-dev --ignore-watch=validators-logo ./src/validators-logo --update:all && yarn copy-files" + "validators-logo:update-all": "ts-node-dev --ignore-watch=validators-logo ./src/validators-logo --update:all && yarn copy-files", + "get-ibc-tokens": "ts-node-dev ./src/services/ibc/tokens.ts" }, "dependencies": { "@injectivelabs/contracts": "^1.14.1-beta.0", diff --git a/packages/sdk-ui-ts/src/denom/DenomClientAsync.ts b/packages/sdk-ui-ts/src/denom/DenomClientAsync.ts index 84fa84d15..725da0a99 100644 --- a/packages/sdk-ui-ts/src/denom/DenomClientAsync.ts +++ b/packages/sdk-ui-ts/src/denom/DenomClientAsync.ts @@ -30,6 +30,8 @@ import { getTokenFromInsuranceFund } from '../utils' import { IbcApplicationsTransferV1Transfer } from '@injectivelabs/core-proto-ts' import { ErrorType, GeneralException } from '@injectivelabs/exceptions' import { awaitForAll } from '@injectivelabs/utils' +// @ts-ignore +import ibcTokenMetadata from '../services/ibc/ibcTokenMetadata.json' const IGNORED_DENOMS = ['peggy0xB855dBC314C39BFa2583567E02a40CBB246CF82B'] @@ -57,6 +59,8 @@ export class DenomClientAsync { IbcApplicationsTransferV1Transfer.DenomTrace > = {} + private cachedIbcTokens: Token[] = [] + constructor( network: Network = Network.Mainnet, options: { endpoints?: NetworkEndpoints; alchemyRpcUrl?: string }, @@ -253,10 +257,19 @@ export class DenomClientAsync { await this.fetchAndCacheDenomTraces() } + if (this.cachedIbcTokens.length === 0) { + await this.fetchAndCacheIbcTokens() + } + const cachedDenomTrace = this.cachedDenomTraces[hash] + const cachedIbcToken = this.cachedIbcTokens.find( + (token) => token?.denom === denom, + ) if (cachedDenomTrace) { - const token = this.denomClient.getDenomToken(cachedDenomTrace.baseDenom) + const token = + this.denomClient.getDenomToken(cachedDenomTrace.baseDenom) || + cachedIbcToken if (!token) { return undefined @@ -276,7 +289,8 @@ export class DenomClientAsync { try { const denomTrace = await this.chainIbcApi.fetchDenomTrace(hash) - const token = this.denomClient.getDenomToken(denomTrace.baseDenom) + const token = + this.denomClient.getDenomToken(denomTrace.baseDenom) || cachedIbcToken if (!token) { return undefined @@ -322,9 +336,18 @@ export class DenomClientAsync { ) } + private async fetchAndCacheIbcTokens() { + if (ibcTokenMetadata?.length === 0) { + return + } + + this.cachedIbcTokens = ibcTokenMetadata as Token[] + } + public async preloadMetadata() { await this.getFactoryDenomMetadata('') await this.getInsuranceFund('') await this.fetchAndCacheDenomTraces() + await this.fetchAndCacheIbcTokens() } } diff --git a/packages/sdk-ui-ts/src/services/ibc/ibcTokenMetadata.json b/packages/sdk-ui-ts/src/services/ibc/ibcTokenMetadata.json new file mode 100644 index 000000000..7e3d54334 --- /dev/null +++ b/packages/sdk-ui-ts/src/services/ibc/ibcTokenMetadata.json @@ -0,0 +1,812 @@ +[ + { + "name": "Injective", + "denom": "inj", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/injective/images/inj.png", + "symbol": "INJ", + "decimals": 18, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "Stride", + "denom": "ibc/3FDD002A3A4019B05A33D324B2F29748E77AF501BEA5C96D1F28B2D6755F9F25", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/stride/images/strd.png", + "symbol": "STRD", + "decimals": 6, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "stATOM", + "denom": "ibc/A8F39212ED30B6A8C2AC736665835720D3D7BE4A1D18D68566525EC25ECF1C9B", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/stride/images/statom.png", + "symbol": "stATOM", + "decimals": 6, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "stSTARS", + "denom": "ibc/DD0F92D576A9A60487F17685A987AB6EDB359E661D281ED31F3AE560650ECFCB", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/stride/images/ststars.png", + "symbol": "stSTARS", + "decimals": 6, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "stOSMO", + "denom": "ibc/6D821F3CFAE78E9EBD872FAEC61C400C0D9B72E77FA14614CF1B775A528854FD", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/stride/images/stosmo.png", + "symbol": "stOSMO", + "decimals": 6, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "stJUNO", + "denom": "ibc/580E52A2C2DB126EE2160D1BDBBA33B5839D53B5E59D04D4FF438AE9BB7BFAAB", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/stride/images/stjuno.png", + "symbol": "stJUNO", + "decimals": 6, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "stLUNA", + "denom": "ibc/E98796F283A8B56A221011C2EDF7079BB62D1EA3EEF3E7CF4C679E91C6D97D08", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/stride/images/stluna.png", + "symbol": "stLUNA", + "decimals": 6, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "stEVMOS", + "denom": "ibc/75F64E20A70C5059F8EA792F1C47260DC7C6CBAC69DBA60E151AD5416E93C34C", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/stride/images/stevmos.png", + "symbol": "stEVMOS", + "decimals": 18, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "stINJ", + "denom": "ibc/AC87717EA002B0123B10A05063E69BCA274BA2C44D842AEEB41558D2856DCE93", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/stride/images/stinj.png", + "symbol": "stINJ", + "decimals": 18, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "stUMEE", + "denom": "ibc/FC8E98DF998AE88129183094E49383F94B3E5F1844C939D380AF18061FEF41EB", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/stride/images/stumee.png", + "symbol": "stUMEE", + "decimals": 6, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "Osmosis", + "denom": "ibc/92E0120F15D037353CFB73C14651FC8930ADC05B93100FD7754D3A689E53B333", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/osmosis/images/osmo.png", + "symbol": "OSMO", + "decimals": 6, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "Ion", + "denom": "ibc/1B2D7E4261A7E2130E8E3506058E3081D3154998413F0DB2F82B04035B3FE676", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/osmosis/images/ion.png", + "symbol": "ION", + "decimals": 6, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "IBCX", + "denom": "ibc/491C92BEEAFE513BABA355275C7AE3AC47AA7FD57285AC1D910CE874D2DC7CA0", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/osmosis/images/ibcx.svg", + "symbol": "IBCX", + "decimals": 6, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "Evmos", + "denom": "ibc/16618B7F7AC551F48C057A13F4CA5503693FBFF507719A85BC6876B8BD75F821", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/evmos/images/evmos.png", + "symbol": "EVMOS", + "decimals": 18, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "Kuji", + "denom": "ibc/9A115B56E769B92621FFF90567E2D60EFD146E86E867491DB69EEDA9ADC36204", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/kujira/images/kuji.png", + "symbol": "KUJI", + "decimals": 6, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "USK", + "denom": "ibc/45D5C97124CFD8AD9CD88AB98815455A7DEDBD932BA725107AD1BE71B85EAF21", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/kujira/images/usk.png", + "symbol": "USK", + "decimals": 6, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "ampKUJI", + "denom": "ibc/C5FA29CE50D543E193DBC6D3D944ACB3A660C96C340F800CFA4BFCF876F9DD74", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/kujira/images/ampKUJI.png", + "symbol": "ampKUJI", + "decimals": 6, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "MNTA", + "denom": "ibc/E517983388553858495A0E716406CF2FD4FE9BCE1EC3C9A71742282448674F10", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/kujira/images/mnta.png", + "symbol": "MNTA", + "decimals": 6, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "WINK", + "denom": "ibc/495694322A85155314DBA1238FDCA84F989E3A3B5A30D5D81FF7865D6445C7E5", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/kujira/images/wink.png", + "symbol": "WINK", + "decimals": 6, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "Axelar", + "denom": "ibc/B68C1D2682A8B69E20BB921E34C6A3A2B6D1E13E3E8C0092E373826F546DEE65", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/axelar/images/axl.png", + "symbol": "AXL", + "decimals": 6, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "USD Coin", + "denom": "ibc/7E1AF94AD246BE522892751046F0C959B768642E5671CC3742264068D49553C0", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/axelar/images/usdc.png", + "symbol": "USDC", + "decimals": 6, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "Frax", + "denom": "ibc/3E5504815B2D69DCC32B1FF54CDAC28D7DA2C445BD29C496A83732DC1D52DB90", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/ethereum/images/frax.svg", + "symbol": "FRAX", + "decimals": 18, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "Dai Stablecoin", + "denom": "ibc/265ABC4B9F767AF45CAC6FB76E930548D835EDA3E94BC56B70582A55A73D8C90", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/axelar/images/dai.png", + "symbol": "DAI", + "decimals": 18, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "Tether USD", + "denom": "ibc/90C6F06139D663CFD7949223D257C5B5D241E72ED61EBD12FFDDA6F068715E47", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/axelar/images/usdt.png", + "symbol": "USDT", + "decimals": 6, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "Wrapped Ether", + "denom": "ibc/65A6973F7A4013335AE5FFE623FE019A78A1FEEE9B8982985099978837D764A7", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/axelar/images/weth.png", + "symbol": "WETH", + "decimals": 18, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "Wrapped Bitcoin", + "denom": "ibc/4C8A332AE4FDE42709649B5F9A2A336192158C4465DF74B4513F5AD0C583EA6F", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/axelar/images/wbtc.png", + "symbol": "WBTC", + "decimals": 8, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "Aave", + "denom": "ibc/49265FCAA6CC20B59652C0B45B2283A260BB19FC183DE95C29CCA8E01F8B004C", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/ethereum/images/aave.svg", + "symbol": "AAVE", + "decimals": 18, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "ApeCoin", + "denom": "ibc/8A13F5DA968B4D526E9DC5AE20B584FE62462E80AF06B9D0EA0B0DB35ABBBF27", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/ethereum/images/ape.svg", + "symbol": "APE", + "decimals": 18, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "Axie Infinity Shard", + "denom": "ibc/EB519ECF709F0DB6BA1359F91BA2DDC5A07FB9869E1768D377EFEF9DF33DC4AB", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/ethereum/images/axs.svg", + "symbol": "AXS", + "decimals": 18, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "Chainlink", + "denom": "ibc/AC447F1D6EDAF817589C5FECECB6CD3B9E9EFFD33C7E16FE8820009F92A2F585", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/ethereum/images/link.png", + "symbol": "LINK", + "decimals": 18, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "Maker", + "denom": "ibc/E8C65EFAB7804152191B8311F61877A36779277E316883D8812D3CBEFC79AE4F", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/ethereum/images/mkr.svg", + "symbol": "MKR", + "decimals": 18, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "Rai Reflex Index", + "denom": "ibc/27817BAE3958FFB2BFBD8F4F6165153DFD230779994A7C42A91E0E45E8201768", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/ethereum/images/rai.svg", + "symbol": "RAI", + "decimals": 18, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "Shiba Inu", + "denom": "ibc/E68343A4DEF4AFBE7C5A9004D4C11888EE755A7B43B3F1AFA52F2C34C07990D5", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/ethereum/images/shib.svg", + "symbol": "SHIB", + "decimals": 18, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "Lido Staked Ether", + "denom": "ibc/FB1B967C690FEA7E9AD7CF76AE2255169D4EA2937D6694B2C0E61A370F76D9FB", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/ethereum/images/steth.svg", + "symbol": "stETH", + "decimals": 18, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "Uniswap", + "denom": "ibc/3E3A8A403AE81114F4341962A6D73162D586C9DF4CE3BE7C7B459108430675F7", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/ethereum/images/uni.svg", + "symbol": "UNI", + "decimals": 18, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "Chain", + "denom": "ibc/79D01DE88DFFC0610003439D38200E77A3D2A1CCCBE4B1958D685026ABB01814", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/ethereum/images/xcn.svg", + "symbol": "XCN", + "decimals": 18, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "Wrapped Polkadot", + "denom": "ibc/624BA9DD171915A2B9EA70F69638B2CEA179959850C1A586F6C485498F29EDD4", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/polkadot/images/dot.png", + "symbol": "DOT", + "decimals": 10, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "Wrapped Moonbeam", + "denom": "ibc/8FF72FB47F07B4AFA8649500A168683BEFCB9EE164BD331FA597D26224D51055", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/moonbeam/images/glmr.png", + "symbol": "WGLMR", + "decimals": 18, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "Wrapped Matic", + "denom": "ibc/7E23647941230DA0AB4ED10F599647D9BE34E1C991D0DA032B5A1522941EBA73", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/polygon/images/wmatic.png", + "symbol": "WMATIC", + "decimals": 18, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "Wrapped BNB", + "denom": "ibc/B877B8EF095028B807370AB5C7790CA0C328777C9FF09AA7F5436BA7FAE4A86F", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/binancesmartchain/images/wbnb.png", + "symbol": "WBNB", + "decimals": 18, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "Binance USD", + "denom": "ibc/A62F794AAEC56B6828541224D91DA3E21423AB0DC4D21ECB05E4588A07BD934C", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/ethereum/images/busd.png", + "symbol": "BUSD", + "decimals": 18, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "Wrapped AVAX", + "denom": "ibc/A4FF8E161D2835BA06A7522684E874EFC91004AD0CD14E038F37940562158D73", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/avalanche/images/wavax.svg", + "symbol": "WAVAX", + "decimals": 18, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "Wrapped FTM", + "denom": "ibc/31E8DDA49D53535F358B29CFCBED1B9224DAAFE82788C0477930DCDE231DA878", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/fantom/images/ftm.png", + "symbol": "WFTM", + "decimals": 18, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "USD Coin from Polygon", + "denom": "ibc/2E93E8914CA07B73A794657DA76170A016057D1C6B0DC42D969918D4F22D95A3", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/axelar/images/usdc.png", + "symbol": "USDC", + "decimals": 6, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "USD Coin from Avalanche", + "denom": "ibc/705E7E25F94467E363B2EB324A5A6FF4C683A4A6D20AAD2AEEABA2D9EB1B897F", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/axelar/images/usdc.png", + "symbol": "USDC", + "decimals": 6, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "Wrapped FIL from Filecoin", + "denom": "ibc/9D1889339AEC850B1D719CCF19BD813955C086BE1ED323ED68318A273922E40D", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/filecoin/images/wfil.png", + "symbol": "axlFIL", + "decimals": 18, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "Arbitrum", + "denom": "ibc/F28C5C931D2673B7A2F06FC74934F7BDC0D2906D2AF40D582ED27D1E5C48D475", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/_non-cosmos/arbitrum/images/arb.png", + "symbol": "ARB", + "decimals": 18, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "Pepe", + "denom": "ibc/9144D78830C5ABD7B7D9E219EA7600E3A0E0AD5FC50C007668160595E94789AB", + "logo": "https://ibc.tfm.com/custom/tokens/pepe-wei.logo.svg", + "symbol": "PEPE", + "decimals": 18, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "Coinbase Wrapped Staked ETH", + "denom": "ibc/545E97C6EFB2633645720DEBCA78B2BE6F5382C4693EA7DEB2D4C456371EA4F0", + "logo": "untracked.svg", + "symbol": "cbETH", + "decimals": 18, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "Rocket Pool Ether", + "denom": "ibc/8906BF683A89D1ABE075A49EFA35A3128D7E9D809775B8E9D5AEEAA55D2889DD", + "logo": "untracked.svg", + "symbol": "rETH", + "decimals": 18, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "Staked Frax Ether", + "denom": "ibc/E918585C09958BD328DD9E7215E4726623E7A9A94342FEA5BE126A2AAF920730", + "logo": "untracked.svg", + "symbol": "sfrxETH", + "decimals": 18, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "Wrapped Lido Staked Ether", + "denom": "ibc/1E0FC59FB8495BF927B10E9D515661494B1BBEDAA15D80E52FE2BADA64656D16", + "logo": "untracked.svg", + "symbol": "wstETH", + "decimals": 18, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "Cosmos Hub Atom", + "denom": "ibc/C4CFF46FD6DE35CA4CF4CE031E643C8FDC9BA4B99AE598E9B0ED98FE3A2319F9", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/cosmoshub/images/atom.png", + "symbol": "ATOM", + "decimals": 6, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "Persistence", + "denom": "ibc/B786E7CBBF026F6F15A8DA248E0F18C62A0F7A70CB2DABD9239398C8B5150ABB", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/persistence/images/xprt.png", + "symbol": "XPRT", + "decimals": 6, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "PSTAKE staked ATOM", + "denom": "ibc/B8E30AECB0FB5BA1B02747BE003E55934A9E42488495412C7E9934FBEC06B201", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/persistence/images/stkatom.png", + "symbol": "stkATOM", + "decimals": 6, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "Whale", + "denom": "ibc/D6E6A20ABDD600742D22464340A7701558027759CE14D12590F8EA869CCCF445", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/migaloo/images/white-whale.png", + "symbol": "WHALE", + "decimals": 6, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "ampWHALE", + "denom": "ibc/168C3904C45C6FE3539AE85A8892DF87371D00EA7942515AFC50AA43C4BB0A32", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/migaloo/images/ampWhale.svg", + "symbol": "ampWHALE", + "decimals": 6, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "boneWHALE", + "denom": "ibc/ECB0AA28D6001EF985047558C410B65581FC85BD92D4E3CFCCA0D3D964C67CC2", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/migaloo/images/bWHALE.png", + "symbol": "bWHALE", + "decimals": 6, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "FABLE", + "denom": "ibc/5FE5E50EA0DF6D68C29EDFB7992EB81CD40B6780C33834A8AB3712FB148E1313", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/migaloo/images/fable.svg", + "symbol": "FABLE", + "decimals": 6, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "Somm", + "denom": "ibc/34346A60A95EB030D62D6F5BDD4B745BE18E8A693372A8A347D5D53DBBB1328B", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/sommelier/images/somm.png", + "symbol": "SOMM", + "decimals": 6, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "Crescent", + "denom": "ibc/3A6DD3358D9F7ADD18CDE79BA10B400511A5DE4AE2C037D7C9639B52ADAF35C6", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/crescent/images/cre.png", + "symbol": "CRE", + "decimals": 6, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "Bonded Crescent", + "denom": "ibc/D9E839DE6F40C036592B6CEDB73841EE9A18987BC099DD112762A46AFE72159B", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/crescent/images/bcre.png", + "symbol": "bCRE", + "decimals": 6, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "Secret Network", + "denom": "ibc/0954E1C28EB7AF5B72D24F3BC2B47BBB2FDF91BDDFD57B74B99E133AED40972A", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/secretnetwork/images/scrt.png", + "symbol": "SCRT", + "decimals": 6, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "Astroport", + "denom": "ibc/EBD5A24C554198EBAF44979C5B4D2C2D312E6EBAB71962C92F735499C7575839", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra/images/astro.png", + "symbol": "ASTRO", + "decimals": 6, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "ERIS Amplified LUNA", + "denom": "ibc/751CCECAF75D686B1DC8708BE62F8C7411B211750E6009C6AC4C93881F0543E8", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra2/images/ampluna.svg", + "symbol": "ampLUNA", + "decimals": 6, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "Lion DAO", + "denom": "ibc/E6CFB0AC1D339A8CBA3353DF0D7E080B4B14D026D1C90F63F666C223B04D548C", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra2/images/roar.png", + "symbol": "ROAR", + "decimals": 6, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "boneLuna", + "denom": "ibc/C9D55B62C9D9CA84DD94DC019009B840DDFD861BF2F33F7CF2A8A74933797680", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra2/images/boneluna.png", + "symbol": "bLUNA", + "decimals": 6, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "Lion Cub DAO", + "denom": "ibc/5CB35B165F689DD57F836C6C5ED3AB268493AA5A810740446C4F2141664714F4", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra2/images/cub.png", + "symbol": "CUB", + "decimals": 6, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "sayve", + "denom": "ibc/DF2B99CF1FEA6B292E79617BD6F7EF735C0B47CEF09D7104E270956E96C38B12", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra2/images/sayve.png", + "symbol": "SAYVE", + "decimals": 6, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "stCMDX", + "denom": "ibc/0CAB2CA45981598C95B6BE18252AEFE1E9E1691D8B4C661997AD7B836FD904D6", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/stride/images/stcmdx.png", + "symbol": "stCMDX", + "decimals": 6, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "stIBCX Core ", + "denom": "ibc/0A6B424A8207047D9FD499F59177BABD8DB08BBC2316B29B702A403BFB414419", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/osmosis/images/stibcx.png", + "symbol": "stIBCX", + "decimals": 6, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "BLUE CUB DAO", + "denom": "ibc/B692197280D4E62F8D9F8E5C0B697DC4C2C680ED6DE8FFF0368E0552C9215607", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra2/images/blue.png", + "symbol": "BLUE", + "decimals": 6, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "ERIS Amplified OSMO", + "denom": "ibc/012D069D557C4DD59A670AA17E809CB7A790D778E364D0BC0A3248105DA6432D", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/osmosis/images/amp.osmo.png", + "symbol": "ampOSMO", + "decimals": 6, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "ASH", + "denom": "ibc/EED40547772504DF629EFEC08892E689CD14498B1C0AD766CD5075BBBEE3D808", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/migaloo/images/ash.svg", + "symbol": "ASH", + "decimals": 6, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "RAC", + "denom": "ibc/0F3A724673F682CF7812D0ED1A0C41D344C09E94C939E79D12712DC7C0676E80", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/migaloo/images/rac.png", + "symbol": "RAC", + "decimals": 6, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "Kava", + "denom": "ibc/57AA1A70A4BC9769C525EBF6386F7A21536E04A79D62E1981EFCEF9428EBB205", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/kava/images/kava.png", + "symbol": "KAVA", + "decimals": 6, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "Hard", + "denom": "ibc/D6C28E07F7343360AC41E15DDD44D79701DDCA2E0C2C41279739C8D4AE5264BC", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/kava/images/hard.png", + "symbol": "HARD", + "decimals": 6, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "Swap", + "denom": "ibc/70CF1A54E23EA4E480DEDA9E12082D3FD5684C3483CBDCE190C5C807227688C5", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/kava/images/swp.png", + "symbol": "SWP", + "decimals": 6, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "USDX", + "denom": "ibc/C78F65E1648A3DFE0BAEB6C4CDA69CC2A75437F1793C0E6386DFDA26393790AE", + "logo": "https://raw.githubusercontent.com/cosmos/chain-registry/master/kava/images/usdx.png", + "symbol": "USDX", + "decimals": 6, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "Tether USD", + "denom": "ibc/58D95D27C82FAC8D0F9F00C3F6097FD70DD6276423768EA95DBFAA2AF8DAE9A2", + "logo": "untracked.svg", + "symbol": "USDT", + "decimals": 6, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + }, + { + "name": "Tether USD", + "denom": "ibc/4ABBEF4C8926DDDB320AE5188CFD63267ABBCEFC0583E4AE05D6E5AA2401DDAB", + "logo": "untracked.svg", + "symbol": "USDT", + "decimals": 6, + "coinGeckoId": "", + "tokenType": "ibc", + "tokenVerification": "external" + } +] \ No newline at end of file diff --git a/packages/sdk-ui-ts/src/services/ibc/tokens.ts b/packages/sdk-ui-ts/src/services/ibc/tokens.ts new file mode 100644 index 000000000..240b07190 --- /dev/null +++ b/packages/sdk-ui-ts/src/services/ibc/tokens.ts @@ -0,0 +1,62 @@ +import { HttpRestClient } from '@injectivelabs/utils' +import path from 'path' +import fs from 'fs' +import { + Token, + TokenType, + TokenVerification, +} from '@injectivelabs/token-metadata' + +type IbcTokenMetadata = { + name: string + symbol: string + contractAddr: string + decimals: number + numberOfPools: number + imageUrl: string + isTrading: boolean +} + +const ibcTokenMetadataApi = new HttpRestClient('https://api.tfm.com/api/v1/') + +const TOKEN_METADATA_PATH = 'ibc/chain/injective-1/tokens' + +function ibcTokenMetadataToToken( + ibcTokenMetadata: IbcTokenMetadata[], +): Token[] { + return ibcTokenMetadata.map((token) => ({ + name: token.name || 'Unknown', + denom: token.contractAddr || '', + logo: token.imageUrl || 'untracked.svg', + symbol: token.symbol || 'Unknown', + decimals: token.decimals || 18, + coinGeckoId: '', + tokenType: TokenType.Ibc, + tokenVerification: TokenVerification.External, + })) +} + +const fetchIbcTokens = async () => { + try { + const response = (await ibcTokenMetadataApi.get(TOKEN_METADATA_PATH)) as { + data: IbcTokenMetadata[] + } + + if (!response.data || !Array.isArray(response.data)) { + return + } + + const ibcTokens = ibcTokenMetadataToToken(response.data) + const outputPath = path.resolve( + `${process.cwd()}/src/services/ibc/ibcTokenMetadata.json`, + ) + + fs.writeFileSync(outputPath, JSON.stringify(ibcTokens, null, 2)) + } catch (e) { + console.log(e) + + return + } +} + +fetchIbcTokens() From 796d20ae006663e9826734c70c5a394c6d7b349a Mon Sep 17 00:00:00 2001 From: Shane K Moore <41407272+shane-moore@users.noreply.github.com> Date: Sat, 30 Sep 2023 14:32:00 -0700 Subject: [PATCH 2/6] chore: msgGrantAllowance and msgRevokeAllowance --- .gitbook/SUMMARY.md | 1 + .gitbook/core-modules/README.md | 1 + .gitbook/core-modules/feegrant.md | 75 ++++++++ .../sdk-ts/src/core/modules/feegrant/index.ts | 4 + .../feegrant/msgs/MsgGrantAllowance.spec.ts | 151 ++++++++++++++++ .../feegrant/msgs/MsgGrantAllowance.ts | 166 ++++++++++++++++++ .../feegrant/msgs/MsgRevokeAllowance.spec.ts | 79 +++++++++ .../feegrant/msgs/MsgRevokeAllowance.ts | 80 +++++++++ .../core/modules/feegrant/utils/allowance.ts | 140 +++++++++++++++ .../src/core/modules/feegrant/utils/index.ts | 1 + packages/sdk-ts/src/core/modules/index.ts | 1 + packages/sdk-ts/src/core/modules/msgs.ts | 4 + .../sdk-ts/src/core/modules/tx/eip712/maps.ts | 6 + packages/ts-types/src/enums.ts | 2 + 14 files changed, 711 insertions(+) create mode 100644 .gitbook/core-modules/feegrant.md create mode 100644 packages/sdk-ts/src/core/modules/feegrant/index.ts create mode 100644 packages/sdk-ts/src/core/modules/feegrant/msgs/MsgGrantAllowance.spec.ts create mode 100644 packages/sdk-ts/src/core/modules/feegrant/msgs/MsgGrantAllowance.ts create mode 100644 packages/sdk-ts/src/core/modules/feegrant/msgs/MsgRevokeAllowance.spec.ts create mode 100644 packages/sdk-ts/src/core/modules/feegrant/msgs/MsgRevokeAllowance.ts create mode 100644 packages/sdk-ts/src/core/modules/feegrant/utils/allowance.ts create mode 100644 packages/sdk-ts/src/core/modules/feegrant/utils/index.ts diff --git a/.gitbook/SUMMARY.md b/.gitbook/SUMMARY.md index 6ff3b1c85..f9bf95bdc 100644 --- a/.gitbook/SUMMARY.md +++ b/.gitbook/SUMMARY.md @@ -61,6 +61,7 @@ * [Core Modules](core-modules/README.md) * [Auction](core-modules/auction.md) * [AuthZ](core-modules/authz.md) + - [Feegrant](core-modules/feegrant.md) * [Bank](core-modules/bank.md) * [Distribution](core-modules/distribution.md) * [Exchange](core-modules/exchange.md) diff --git a/.gitbook/core-modules/README.md b/.gitbook/core-modules/README.md index 65f95d10a..f7968321b 100644 --- a/.gitbook/core-modules/README.md +++ b/.gitbook/core-modules/README.md @@ -10,6 +10,7 @@ Within this section, we are going to explore the core modules of the Injective c | ------------------------------- | ------------------------------------------------ | | [Auction](auction.md) | Use for the buy-back-and-burn on chain mechanism | | [AuthZ](authz.md) | Used for granting account priveledges | +| [Feegrant](feegrant.md) | Used for granting fee allowance priveledges | | [Bank](bank.md) | Used for managing users assets (funds) | | [Exchange](exchange.md) | Used for the exchange primitives | | [Distribution](distribution.md) | Used for on-chain distribution/minting | diff --git a/.gitbook/core-modules/feegrant.md b/.gitbook/core-modules/feegrant.md new file mode 100644 index 000000000..c052621d6 --- /dev/null +++ b/.gitbook/core-modules/feegrant.md @@ -0,0 +1,75 @@ +# Fee Grant + +The `feegrant` module allows accounts (granters) to grant fee allowances to other accounts (grantees). This allows the grantee to use the granter's funds to pay for transaction fees. + +## Messages + +### MsgGrantAllowance + +A fee allowance grant is created using the `MsgGrantAllowance` message. If there is already a grant for the (granter, grantee) pair, then the new grant will overwrite the previous one. + +```ts +import { MsgGrantAllowance, MsgBroadcasterWithPk } from '@injectivelabs/sdk-ts' +import { Network } from '@injectivelabs/networks' + + +const privateKeyOfGranter = '0x...' + +const date = new Date('2023-10-02T00:00:00Z') +const expiration = date.getTime() / 1000 +const granter = 'inj...' +const grantee = 'inj...' +const allowance = { + spendLimit: [ + { + denom: 'inj', + amount: '10000', + }, + ], + expiration +} + +const msg = MsgGrantAllowance.fromJSON({ + granter, + grantee, + allowance, +}) + +const txHash = await new MsgBroadcasterWithPk({ +privateKey: privateKeyOfGranter, +network: Network.Testnet, +}).broadcast({ +msgs: msg, +}) + +console.log(txHash) + +``` + +### MsgRevokeAllowance +A grant can be removed using the MsgRevokeAllowance message. The grantee will no longer be able to use the granter's funds to pay for transaction fees. + +```ts +import { MsgRevokeAllowance, MsgBroadcasterWithPk } from '@injectivelabs/sdk-ts' +import { Network } from '@injectivelabs/networks' + +const privateKey= "0x..." +const granteeAddress = 'inj...' +const granterAddress = 'inj...' + +const params = { +grantee: granteeAddress, +granter: granterAddress, +} + +const msg = MsgRevokeAllowance.fromJSON(params); + +const txHash = await new MsgBroadcasterWithPk({ +privateKey, +network: Network.Testnet, +}).broadcast({ +msgs: msg, +}) + +console.log(txHash) +``` diff --git a/packages/sdk-ts/src/core/modules/feegrant/index.ts b/packages/sdk-ts/src/core/modules/feegrant/index.ts new file mode 100644 index 000000000..be0443536 --- /dev/null +++ b/packages/sdk-ts/src/core/modules/feegrant/index.ts @@ -0,0 +1,4 @@ +import MsgGrantAllowance from './msgs/MsgGrantAllowance' +import MsgRevokeAllowance from './msgs/MsgRevokeAllowance' + +export { MsgGrantAllowance, MsgRevokeAllowance } diff --git a/packages/sdk-ts/src/core/modules/feegrant/msgs/MsgGrantAllowance.spec.ts b/packages/sdk-ts/src/core/modules/feegrant/msgs/MsgGrantAllowance.spec.ts new file mode 100644 index 000000000..15b6808eb --- /dev/null +++ b/packages/sdk-ts/src/core/modules/feegrant/msgs/MsgGrantAllowance.spec.ts @@ -0,0 +1,151 @@ +import MsgGrantAllowance from './MsgGrantAllowance' +import { mockFactory } from '@injectivelabs/test-utils' +import { CosmosFeegrantV1Beta1Feegrant } from '@injectivelabs/core-proto-ts' +import snakecaseKeys from 'snakecase-keys' + +const { injectiveAddress, injectiveAddress2 } = mockFactory + +const params: MsgGrantAllowance['params'] = { + grantee: injectiveAddress, + granter: injectiveAddress2, + allowance: { + spendLimit: [ + { + denom: 'inj', + amount: '1000', + }, + ], + expiration: 1679416772, + }, +} + +const protoType = '/cosmos.feegrant.v1beta1.MsgGrantAllowance' +const protoTypeShort = 'cosmos-sdk/MsgGrantAllowance' +const protoParams = { + grantee: params.grantee, + granter: params.granter, + allowance: { + typeUrl: '/cosmos.feegrant.v1beta1.BasicAllowance', + value: Uint8Array.from( + CosmosFeegrantV1Beta1Feegrant.BasicAllowance.encode({ + spendLimit: params.allowance.spendLimit, + expiration: new Date(params.allowance.expiration! * 1000), + }).finish(), + ), + }, +} + +const protoParamsAmino = snakecaseKeys({ + grantee: params.grantee, + granter: params.granter, + allowance: { + type: 'cosmos-sdk/BasicAllowance', + value: { + spendLimit: params.allowance.spendLimit, + expiration: new Date(params.allowance.expiration! * 1000), + }, + }, +}) + +const protoParamsWeb3 = { + grantee: params.grantee, + granter: params.granter, + allowance: { + '@type': '/cosmos.feegrant.v1beta1.BasicAllowance', + spendLimit: params.allowance.spendLimit, + expiration: new Date(params.allowance.expiration! * 1000), + }, +} +const message = MsgGrantAllowance.fromJSON(params) + +describe('MsgGrantAllowance', () => { + it('generates proper proto', () => { + const message = MsgGrantAllowance.fromJSON(params) + const proto = message.toProto() + + expect(proto).toStrictEqual({ + ...protoParams, + }) + }) + + it('generates proper data', () => { + const data = message.toData() + + expect(data).toStrictEqual({ + '@type': protoType, + ...protoParams, + }) + }) + + it('generates proper amino', () => { + const amino = message.toAmino() + + expect(amino).toStrictEqual({ + type: protoTypeShort, + value: protoParamsAmino, + }) + }) + + it('generates proper Eip712 types', () => { + const eip712Types = message.toEip712Types() + + expect(Object.fromEntries(eip712Types)).toStrictEqual({ + TypeAllowance: [ + { name: 'type', type: 'string' }, + { name: 'value', type: 'TypeAllowanceValue' }, + ], + TypeAllowanceValue: [ + { name: 'spend_limit', type: 'TypeAllowanceValueSpendLimit[]' }, + { name: 'expiration', type: 'string' }, + ], + TypeAllowanceValueSpendLimit: [ + { name: 'denom', type: 'string' }, + { name: 'amount', type: 'string' }, + ], + MsgValue: [ + { name: 'granter', type: 'string' }, + { name: 'grantee', type: 'string' }, + { name: 'allowance', type: 'TypeAllowance' }, + ], + }) + }) + + it('generates proper Eip712 values', () => { + const eip712 = message.toEip712() + + expect(eip712).toStrictEqual({ + type: protoTypeShort, + value: snakecaseKeys({ + ...protoParamsAmino, + allowance: { + ...protoParamsAmino.allowance, + value: { + ...protoParamsAmino.allowance.value, + expiration: + protoParamsAmino.allowance.value.expiration + .toJSON() + .split('.')[0] + 'Z', + }, + }, + }), + }) + }) + + it('generates proper direct sign', () => { + const directSign = message.toDirectSign() + + expect(directSign).toStrictEqual({ + type: protoType, + message: protoParams, + }) + }) + + it('generates proper web3', () => { + const web3 = message.toWeb3() + + expect(web3).toStrictEqual({ + '@type': protoType, + ...protoParamsWeb3, + }) + }) +}) diff --git a/packages/sdk-ts/src/core/modules/feegrant/msgs/MsgGrantAllowance.ts b/packages/sdk-ts/src/core/modules/feegrant/msgs/MsgGrantAllowance.ts new file mode 100644 index 000000000..8c325b448 --- /dev/null +++ b/packages/sdk-ts/src/core/modules/feegrant/msgs/MsgGrantAllowance.ts @@ -0,0 +1,166 @@ +import snakecaseKeys from 'snakecase-keys' +import { MsgBase } from '../../MsgBase' +import { + CosmosFeegrantV1Beta1Tx, + CosmosFeegrantV1Beta1Feegrant, + GoogleProtobufTimestamp, + GoogleProtobufAny, +} from '@injectivelabs/core-proto-ts' +import { Coin } from '@injectivelabs/ts-types' + +const basicAllowanceType = '/cosmos.feegrant.v1beta1.BasicAllowance' +export declare namespace MsgGrantAllowance { + export interface Params { + granter: string + grantee: string + allowance: { + spendLimit: Coin[] + expiration: number | undefined + } + } + + export type Proto = CosmosFeegrantV1Beta1Tx.MsgGrantAllowance + + export type Object = Omit< + CosmosFeegrantV1Beta1Tx.MsgGrantAllowance, + 'allowance' + > & { + allowance: any + } +} + +/** + * @category Messages + */ +export default class MsgGrantAllowance extends MsgBase< + MsgGrantAllowance.Params, + MsgGrantAllowance.Proto +> { + static fromJSON(params: MsgGrantAllowance.Params): MsgGrantAllowance { + return new MsgGrantAllowance(params) + } + + public toProto() { + const { params } = this + + const timestamp = this.getTimestamp() + const basicAllowance = CosmosFeegrantV1Beta1Feegrant.BasicAllowance.create() + basicAllowance.spendLimit = params.allowance.spendLimit + basicAllowance.expiration = new Date(Number(timestamp.seconds) * 1000) + + const allowance = GoogleProtobufAny.Any.create() + allowance.typeUrl = basicAllowanceType + allowance.value = Buffer.from( + CosmosFeegrantV1Beta1Feegrant.BasicAllowance.encode( + basicAllowance, + ).finish(), + ) + + const message = CosmosFeegrantV1Beta1Tx.MsgGrantAllowance.create() + message.grantee = params.grantee + message.granter = params.granter + message.allowance = allowance + console.log({ + message, + fromJSON: CosmosFeegrantV1Beta1Tx.MsgGrantAllowance.fromJSON(message), + }) + + return CosmosFeegrantV1Beta1Tx.MsgGrantAllowance.fromJSON(message) + } + + public toData() { + const proto = this.toProto() + + return { + '@type': '/cosmos.feegrant.v1beta1.MsgGrantAllowance', + ...proto, + } + } + + public toAmino() { + const { params } = this + + const proto = this.toProto() + const timestamp = this.getTimestamp() + const message = proto + + const messageWithAllowance = snakecaseKeys({ + ...message, + allowance: { + type: 'cosmos-sdk/BasicAllowance', + value: { + spendLimit: params.allowance.spendLimit, + expiration: new Date(Number(timestamp.seconds) * 1000), + }, + }, + }) + + return { + type: 'cosmos-sdk/MsgGrantAllowance', + value: messageWithAllowance as unknown as MsgGrantAllowance.Object, + } + } + + public toDirectSign() { + const proto = this.toProto() + + return { + type: '/cosmos.feegrant.v1beta1.MsgGrantAllowance', + message: proto, + } + } + + public toWeb3() { + const { params } = this + const amino = this.toAmino() + const timestamp = this.getTimestamp() + + const messageWithAllowance = { + granter: amino.value.granter, + grantee: amino.value.grantee, + allowance: { + '@type': basicAllowanceType, + spendLimit: params.allowance.spendLimit, + expiration: new Date(Number(timestamp.seconds) * 1000), + }, + } + + return { + '@type': '/cosmos.feegrant.v1beta1.MsgGrantAllowance', + ...messageWithAllowance, + } + } + + private getTimestamp() { + const { params } = this + + if (params.allowance.expiration) { + const timestamp = GoogleProtobufTimestamp.Timestamp.create() + + timestamp.seconds = params.allowance.expiration.toString() + + return timestamp + } + + const defaultExpiryYears = 5 + const dateNow = new Date() + const expiration = new Date( + dateNow.getFullYear() + defaultExpiryYears, + dateNow.getMonth(), + dateNow.getDate(), + ) + + const timestamp = GoogleProtobufTimestamp.Timestamp.create() + const timestampInSeconds = (expiration.getTime() / 1000).toString() + + timestamp.seconds = timestampInSeconds + + return timestamp + } + + public toBinary(): Uint8Array { + return CosmosFeegrantV1Beta1Tx.MsgGrantAllowance.encode( + this.toProto(), + ).finish() + } +} diff --git a/packages/sdk-ts/src/core/modules/feegrant/msgs/MsgRevokeAllowance.spec.ts b/packages/sdk-ts/src/core/modules/feegrant/msgs/MsgRevokeAllowance.spec.ts new file mode 100644 index 000000000..89ee5a3bc --- /dev/null +++ b/packages/sdk-ts/src/core/modules/feegrant/msgs/MsgRevokeAllowance.spec.ts @@ -0,0 +1,79 @@ +import MsgRevokeAllowance from './MsgRevokeAllowance' +import { mockFactory } from '@injectivelabs/test-utils' +import snakecaseKeys from 'snakecase-keys' + +const { injectiveAddress, injectiveAddress2 } = mockFactory + +const params: MsgRevokeAllowance['params'] = { + grantee: injectiveAddress, + granter: injectiveAddress2, +} + +const protoType = '/cosmos.feegrant.v1beta1.MsgRevokeAllowance' +const protoTypeShort = 'cosmos-sdk/MsgRevokeAllowance' +const protoParams = { + grantee: params.grantee, + granter: params.granter, +} + +const protoParamsAmino = snakecaseKeys(protoParams) +const message = MsgRevokeAllowance.fromJSON(params) + +describe('MsgRevokeAllowance', () => { + it('generates proper proto', () => { + const proto = message.toProto() + + expect(proto).toStrictEqual({ + ...protoParams, + }) + }) + + it('generates proper data', () => { + const data = message.toData() + + expect(data).toStrictEqual({ + '@type': protoType, + ...protoParams, + }) + }) + + it('generates proper amino', () => { + const amino = message.toAmino() + + expect(amino).toStrictEqual({ + type: protoTypeShort, + value: protoParamsAmino, + }) + }) + + it('generates proper Eip712 types', () => { + const eip712Types = message.toEip712Types() + + expect(Object.fromEntries(eip712Types)).toStrictEqual({ + MsgValue: [ + { name: 'granter', type: 'string' }, + { name: 'grantee', type: 'string' }, + ], + }) + }) + + it('generates proper Eip712 values', () => { + const eip712 = message.toEip712() + + expect(eip712).toStrictEqual({ + type: protoTypeShort, + value: snakecaseKeys({ + ...protoParamsAmino, + }), + }) + }) + + it('generates proper web3', () => { + const web3 = message.toWeb3() + + expect(web3).toStrictEqual({ + '@type': protoType, + ...protoParamsAmino, + }) + }) +}) diff --git a/packages/sdk-ts/src/core/modules/feegrant/msgs/MsgRevokeAllowance.ts b/packages/sdk-ts/src/core/modules/feegrant/msgs/MsgRevokeAllowance.ts new file mode 100644 index 000000000..1dd2599dd --- /dev/null +++ b/packages/sdk-ts/src/core/modules/feegrant/msgs/MsgRevokeAllowance.ts @@ -0,0 +1,80 @@ +import { MsgBase } from '../../MsgBase' +import snakecaseKeys, { SnakeCaseKeys } from 'snakecase-keys' +import { CosmosFeegrantV1Beta1Tx } from '@injectivelabs/core-proto-ts' + +export declare namespace MsgRevokeAllowance { + export interface Params { + granter: string + grantee: string + } + + export type Proto = CosmosFeegrantV1Beta1Tx.MsgRevokeAllowance +} + +/** + * @category Messages + */ +export default class MsgRevokeAllowance extends MsgBase< + MsgRevokeAllowance.Params, + MsgRevokeAllowance.Proto +> { + static fromJSON(params: MsgRevokeAllowance.Params): MsgRevokeAllowance { + return new MsgRevokeAllowance(params) + } + + public toProto() { + const { params } = this + + const message = CosmosFeegrantV1Beta1Tx.MsgRevokeAllowance.create() + message.grantee = params.grantee + message.granter = params.granter + + return CosmosFeegrantV1Beta1Tx.MsgRevokeAllowance.fromPartial(message) + } + + public toData() { + const proto = this.toProto() + + return { + '@type': '/cosmos.feegrant.v1beta1.MsgRevokeAllowance', + ...proto, + } + } + + public toAmino() { + const proto = this.toProto() + const message = { + ...snakecaseKeys(proto), + } + + return { + type: 'cosmos-sdk/MsgRevokeAllowance', + value: message as unknown as SnakeCaseKeys, + } + } + + public toWeb3() { + const amino = this.toAmino() + const { value } = amino + + return { + '@type': '/cosmos.feegrant.v1beta1.MsgRevokeAllowance', + ...value, + } + } + + public toDirectSign() { + const proto = this.toProto() + + return { + type: '/cosmos.feegrant.v1beta1.MsgRevokeAllowance', + message: proto, + } + } + + public toBinary(): Uint8Array { + return CosmosFeegrantV1Beta1Tx.MsgRevokeAllowance.encode( + this.toProto(), + ).finish() + } +} diff --git a/packages/sdk-ts/src/core/modules/feegrant/utils/allowance.ts b/packages/sdk-ts/src/core/modules/feegrant/utils/allowance.ts new file mode 100644 index 000000000..7e50a0e83 --- /dev/null +++ b/packages/sdk-ts/src/core/modules/feegrant/utils/allowance.ts @@ -0,0 +1,140 @@ +import { + GoogleProtobufAny, + CosmosFeegrantV1Beta1Feegrant, +} from '@injectivelabs/core-proto-ts' +import { GeneralException } from '@injectivelabs/exceptions' + +export type AllowedMsgAllowance = Omit< + CosmosFeegrantV1Beta1Feegrant.AllowedMsgAllowance, + 'allowance' +> & { + allowance: + | CosmosFeegrantV1Beta1Feegrant.BasicAllowance + | CosmosFeegrantV1Beta1Feegrant.PeriodicAllowance +} + +export type Allowance = + | CosmosFeegrantV1Beta1Feegrant.BasicAllowance + | CosmosFeegrantV1Beta1Feegrant.PeriodicAllowance + | AllowedMsgAllowance + | undefined + +export enum AllowanceTypes { + BasicAllowance = 'spendLimit', + PeriodicAllowance = 'periodSpendLimit', + AllowedMsgAllowance = 'allowedMessages', +} + +function isBasicAllowance( + allowance: Allowance, +): allowance is CosmosFeegrantV1Beta1Feegrant.BasicAllowance { + if (!allowance) { + return false + } + + return AllowanceTypes.BasicAllowance in allowance +} + +function isPeriodicAllowance( + allowance: Allowance, +): allowance is CosmosFeegrantV1Beta1Feegrant.PeriodicAllowance { + if (!allowance) { + return false + } + + return AllowanceTypes.PeriodicAllowance in allowance +} + +function isAllowedMsgAllowance( + allowance: Allowance, +): allowance is AllowedMsgAllowance { + if (!allowance) { + return false + } + + return AllowanceTypes.AllowedMsgAllowance in allowance +} + +function encodeBasicAllowance( + allowance: CosmosFeegrantV1Beta1Feegrant.BasicAllowance, +): GoogleProtobufAny.Any { + return { + typeUrl: '/cosmos.feegrant.v1beta1.BasicAllowance', + value: Buffer.from( + CosmosFeegrantV1Beta1Feegrant.BasicAllowance.encode(allowance).finish(), + ), + } +} + +function encodePeriodicAllowance( + allowance: CosmosFeegrantV1Beta1Feegrant.PeriodicAllowance, +): GoogleProtobufAny.Any { + return { + typeUrl: '/cosmos.feegrant.v1beta1.PeriodicAllowance', + value: Buffer.from( + CosmosFeegrantV1Beta1Feegrant.PeriodicAllowance.encode( + allowance, + ).finish(), + ), + } +} + +function encodeAllowedMsgAllowance( + allowance: AllowedMsgAllowance, +): GoogleProtobufAny.Any | undefined { + let internalAllowance: GoogleProtobufAny.Any + + if (isBasicAllowance(allowance.allowance as Allowance)) { + internalAllowance = encodeBasicAllowance( + allowance.allowance as unknown as CosmosFeegrantV1Beta1Feegrant.BasicAllowance, + ) + } else if (isPeriodicAllowance(allowance.allowance as Allowance)) { + internalAllowance = encodePeriodicAllowance( + allowance.allowance as unknown as CosmosFeegrantV1Beta1Feegrant.PeriodicAllowance, + ) + } else { + throw new Error( + `AllowedMsgAllowance: Cannot cast allowance into 'BasicAllowance' or 'PeriodicAllowance': ${JSON.stringify( + allowance.allowance, + )}`, + ) + } + + return { + typeUrl: '/cosmos.feegrant.v1beta1.AllowedMsgAllowance', + value: Buffer.from( + CosmosFeegrantV1Beta1Feegrant.AllowedMsgAllowance.encode({ + allowedMessages: allowance.allowedMessages, + allowance: internalAllowance, + }).finish(), + ), + } +} + +export function encodeAllowance( + allowance: Allowance, +): GoogleProtobufAny.Any | undefined { + if (isBasicAllowance(allowance)) { + return encodeBasicAllowance( + allowance as CosmosFeegrantV1Beta1Feegrant.BasicAllowance, + ) + } + + if (isPeriodicAllowance(allowance)) { + return encodePeriodicAllowance( + allowance as CosmosFeegrantV1Beta1Feegrant.PeriodicAllowance, + ) + } + + if (isAllowedMsgAllowance(allowance)) { + return encodeAllowedMsgAllowance(allowance as AllowedMsgAllowance) + } + + throw new GeneralException( + new Error( + `Cannot cast allowance into 'BasicAllowance', 'PeriodicAllowance' or 'AllowedMsgAllowance': ${JSON.stringify( + allowance, + )}`, + ), + ) +} diff --git a/packages/sdk-ts/src/core/modules/feegrant/utils/index.ts b/packages/sdk-ts/src/core/modules/feegrant/utils/index.ts new file mode 100644 index 000000000..48a402756 --- /dev/null +++ b/packages/sdk-ts/src/core/modules/feegrant/utils/index.ts @@ -0,0 +1 @@ +export * from './allowance' diff --git a/packages/sdk-ts/src/core/modules/index.ts b/packages/sdk-ts/src/core/modules/index.ts index b88650c8e..e108a6fb6 100644 --- a/packages/sdk-ts/src/core/modules/index.ts +++ b/packages/sdk-ts/src/core/modules/index.ts @@ -12,3 +12,4 @@ export * from './tokenfactory' export * from './wasm' export * from './tx' export * from './msgs' +export * from './feegrant' diff --git a/packages/sdk-ts/src/core/modules/msgs.ts b/packages/sdk-ts/src/core/modules/msgs.ts index f61caccde..6928dc4cd 100644 --- a/packages/sdk-ts/src/core/modules/msgs.ts +++ b/packages/sdk-ts/src/core/modules/msgs.ts @@ -4,6 +4,8 @@ import MsgRevoke from './authz/msgs/MsgRevoke' import MsgAuthzExec from './authz/msgs/MsgExec' import MsgSend from './bank/msgs/MsgSend' import MsgMultiSend from './bank/msgs/MsgMultiSend' +import MsgGrantAllowance from './feegrant/msgs/MsgGrantAllowance' +import MsgRevokeAllowance from './feegrant/msgs/MsgRevokeAllowance' import MsgWithdrawDelegatorReward from './distribution/msgs/MsgWithdrawDelegatorReward' import MsgWithdrawValidatorCommission from './distribution/msgs/MsgWithdrawValidatorCommission' import MsgBatchCancelDerivativeOrders from './exchange/msgs/MsgBatchCancelDerivativeOrders' @@ -109,6 +111,8 @@ export type Msgs = | MsgChangeAdmin | MsgCreateDenom | MsgSetDenomMetadata + | MsgGrantAllowance + | MsgRevokeAllowance /** * @category Messages diff --git a/packages/sdk-ts/src/core/modules/tx/eip712/maps.ts b/packages/sdk-ts/src/core/modules/tx/eip712/maps.ts index 65a86b0d7..330f69325 100644 --- a/packages/sdk-ts/src/core/modules/tx/eip712/maps.ts +++ b/packages/sdk-ts/src/core/modules/tx/eip712/maps.ts @@ -629,6 +629,12 @@ export const protoTypeToAminoType = (type: string): string => { case 'ibc.applications.transfer.v1.MsgTransfer': return 'cosmos-sdk/MsgTransfer' + // feegrant + case 'cosmos.feegrant.v1beta1.MsgGrantAllowance': + return 'cosmos-sdk/MsgGrantAllowance' + case 'cosmos.feegrant.v1beta1.MsgRevokeAllowance': + return 'cosmos-sdk/MsgRevokeAllowance' + default: throw new GeneralException(new Error('Unknown message type: ' + type)) } diff --git a/packages/ts-types/src/enums.ts b/packages/ts-types/src/enums.ts index 2e01dac6d..e7a4bc341 100644 --- a/packages/ts-types/src/enums.ts +++ b/packages/ts-types/src/enums.ts @@ -18,9 +18,11 @@ export enum ChainId { export enum MsgType { MsgExec = 'cosmos.authz.v1beta1.MsgExec', MsgGrant = 'cosmos.authz.v1beta1.MsgGrant', + MsgRevoke = 'cosmos.authz.v1beta1.MsgRevoke', MsgSend = 'cosmos.bank.v1beta1.MsgSend', MsgWithdrawDelegatorReward = 'cosmos.distribution.v1beta1.MsgWithdrawDelegatorReward', MsgGrantAllowance = 'cosmos.feegrant.v1beta1.MsgGrantAllowance', + MsgRevokeAllowance = 'cosmos.feegrant.v1beta1.MsgRevokeAllowance', MsgDepositCosmos = 'cosmos.gov.v1beta1.MsgDeposit', MsgSubmitProposal = 'cosmos.gov.v1beta1.MsgSubmitProposal', MsgVote = 'cosmos.gov.v1beta1.MsgVote', From d136734b41e177a978ac2c350bb5d99625439b1a Mon Sep 17 00:00:00 2001 From: Shane K Moore <41407272+shane-moore@users.noreply.github.com> Date: Sat, 30 Sep 2023 14:39:29 -0700 Subject: [PATCH 3/6] chore: add MsgExecuteContractCompat docs context --- .gitbook/core-modules/wasm.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.gitbook/core-modules/wasm.md b/.gitbook/core-modules/wasm.md index c6e423270..39e5debe6 100644 --- a/.gitbook/core-modules/wasm.md +++ b/.gitbook/core-modules/wasm.md @@ -82,7 +82,9 @@ console.log(txHash); ### MsgExecuteContractCompact -There are some compatibility issue parsing the funds array in the previous example with EIP712, hence we introduced MsgExecuteContractCompact which converts the funds into a string +There are some compatibility issue parsing the funds array in the previous example with EIP712. +Since MsgExecuteContract can't be converted to EIP712 and then signed by ethereum wallets, we introduced MsgExecuteContractCompact which converts the funds into a string and therefore allows for EIP712 transformation. +Note that the MsgExecuteContract and MsgExecuteContractCompat underlying messages are the same. MsgExecuteContractCompat will just format for EIP712 compatibility. An array of funds: From 61ec73193de330f82c0af1e619e86c10cb09f628 Mon Sep 17 00:00:00 2001 From: thomasRalee Date: Thu, 12 Oct 2023 17:57:31 +0800 Subject: [PATCH 4/6] fix: docs calculations typo --- .gitbook/README.md | 1 + .gitbook/SUMMARY.md | 1 + .gitbook/{calulations => calculations}/README.md | 0 .gitbook/{calulations => calculations}/minPriceTickSize.md | 0 .gitbook/{calulations => calculations}/minQuantityTickSize.md | 0 5 files changed, 2 insertions(+) rename .gitbook/{calulations => calculations}/README.md (100%) rename .gitbook/{calulations => calculations}/minPriceTickSize.md (100%) rename .gitbook/{calulations => calculations}/minQuantityTickSize.md (100%) diff --git a/.gitbook/README.md b/.gitbook/README.md index 22a8c72d9..0335017be 100644 --- a/.gitbook/README.md +++ b/.gitbook/README.md @@ -21,3 +21,4 @@ _Note: Reading the Technical Concepts section after reading the overview below i * [Core Modules](core-modules/) - In this section we are going to have a quick summary of the core modules on Injective and show examples of how to create some Messages (+ pack them into a transaction, sign them using a private key, and broadcast them on Injective) within these core modules. * [Bridge](bridge/) - In this section, we are going to have a look at Injective's interoperability and explain how developers can utilize the Peggy bridge and the IBC bridge to bridge assets over to Injective. * [Networks](readme/networks.md) - In this section, we will look at different (pre-defined) available Networks for developers to utilize while building dApps on top of Injective, allowing them to start building without the need to make their own infrastructure. +* [Calculations](calculations/) - In this section, we will look at different calculations formula converting values between UI human-readable and chain format. diff --git a/.gitbook/SUMMARY.md b/.gitbook/SUMMARY.md index 6ff3b1c85..dc527c644 100644 --- a/.gitbook/SUMMARY.md +++ b/.gitbook/SUMMARY.md @@ -84,3 +84,4 @@ * [Smart Contract](building-dapps/smart-contract.md) * [DEX](building-dapps/dex.md) * [Bridge](building-dapps/bridge.md) +* [Calculations](calculations/README.md) diff --git a/.gitbook/calulations/README.md b/.gitbook/calculations/README.md similarity index 100% rename from .gitbook/calulations/README.md rename to .gitbook/calculations/README.md diff --git a/.gitbook/calulations/minPriceTickSize.md b/.gitbook/calculations/minPriceTickSize.md similarity index 100% rename from .gitbook/calulations/minPriceTickSize.md rename to .gitbook/calculations/minPriceTickSize.md diff --git a/.gitbook/calulations/minQuantityTickSize.md b/.gitbook/calculations/minQuantityTickSize.md similarity index 100% rename from .gitbook/calulations/minQuantityTickSize.md rename to .gitbook/calculations/minQuantityTickSize.md From 9158df298f18aef9a01eeb608c2c109632012d4e Mon Sep 17 00:00:00 2001 From: Bojan Angjelkoski Date: Fri, 13 Oct 2023 09:46:56 +0200 Subject: [PATCH 5/6] chore: update --- .gitbook/transactions/ethereum.md | 88 ++++++++------- .gitbook/transactions/transactions-cosmos.md | 110 ++++++++++--------- 2 files changed, 99 insertions(+), 99 deletions(-) diff --git a/.gitbook/transactions/ethereum.md b/.gitbook/transactions/ethereum.md index 843cc3e04..fa415f959 100644 --- a/.gitbook/transactions/ethereum.md +++ b/.gitbook/transactions/ethereum.md @@ -9,7 +9,7 @@ First of, we need to prepare the transaction for signing. To use Ethereum native Using our custom abstraction for the Messages which allows the developer to get EIP712 TypedData straight from the proto file of the particular message. ```ts -import { +import { MsgSend, ChainRestAuthApi, ChainRestTendermintApi, @@ -17,22 +17,24 @@ import { DEFAULT_STD_FEE, getEip712TypedData, } from '@injectivelabs/sdk-ts' -import { DEFAULT_STD_FEE, DEFAULT_BLOCK_TIMEOUT_HEIGHT } from '@injectivelabs/utils' +import { + DEFAULT_STD_FEE, + DEFAULT_BLOCK_TIMEOUT_HEIGHT, +} from '@injectivelabs/utils' import { ChainId } from '@injectivelabs/ts-types' import { Network, getNetworkEndpoints } from '@injectivelabs/networks' const injectiveAddress = 'inj1' const chainId = 'injective-1' /* ChainId.Mainnet */ -const restEndpoint = 'https://lcd.injective.network' /* getNetworkEndpoints(Network.Mainnet).rest */ +const restEndpoint = + 'https://lcd.injective.network' /* getNetworkEndpoints(Network.Mainnet).rest */ const amount = { amount: new BigNumberInBase(0.01).toWei().toFixed(), - denom: "inj", -}; + denom: 'inj', +} /** Account Details **/ -const chainRestAuthApi = new ChainRestAuthApi( - restEndpoint, -) +const chainRestAuthApi = new ChainRestAuthApi(restEndpoint) const accountDetailsResponse = await chainRestAuthApi.fetchAccount( injectiveAddress, ) @@ -40,9 +42,7 @@ const baseAccount = BaseAccount.fromRestApi(accountDetailsResponse) const accountDetails = baseAccount.toAccountDetails() /** Block Details */ -const chainRestTendermintApi = new ChainRestTendermintApi( - restEndpoint, -) +const chainRestTendermintApi = new ChainRestTendermintApi(restEndpoint) const latestBlock = await chainRestTendermintApi.fetchLatestBlock() const latestHeight = latestBlock.header.height const timeoutHeight = new BigNumberInBase(latestHeight).plus( @@ -54,7 +54,7 @@ const msg = MsgSend.fromJSON({ amount, srcInjectiveAddress: injectiveAddress, dstInjectiveAddress: injectiveAddress, -}); +}) /** EIP712 for signing on Ethereum wallets */ const eip712TypedData = getEip712TypedData({ @@ -77,14 +77,14 @@ Once we have prepared the EIP712 typed data, we proceed to signing. /** Use your preferred approach to sign EIP712 TypedData, example with Metamask */ const signature = await window.ethereum.request({ method: 'eth_signTypedData_v4', - params: [ethereumAddress, JSON.stringify(eip712TypedData /* from previous step */)], + params: [ + ethereumAddress, + JSON.stringify(eip712TypedData /* from previous step */), + ], }) /** Get Public Key of the signer */ -const publicKeyHex = recoverTypedSignaturePubKey( - eip712TypedData, - signature, -) +const publicKeyHex = recoverTypedSignaturePubKey(eip712TypedData, signature) const publicKeyBase64 = hexToBase64(publicKeyHex) ``` @@ -97,7 +97,11 @@ Once we have the signature ready, we need to broadcast the transaction to the In ```ts import { ChainId } from '@injectivelabs/ts-types' import { createTransaction, TxRestClient } from '@injectivelabs/sdk-ts' -import { SIGN_AMINO, Network, getNetworkEndpoints } from '@injectivelabs/networks' +import { + SIGN_AMINO, + Network, + getNetworkEndpoints, +} from '@injectivelabs/networks' const { txRaw } = createTransaction({ message: msgs, @@ -119,19 +123,20 @@ const txRawEip712 = createTxRawEIP712(txRaw, web3Extension) txRawEip712.signatures = [signatureBuff /* From previous step */] /** Broadcast the Transaction */ -const restEndpoint = 'https://lcd.injective.network' /* getNetworkEndpoints(Network.Mainnet).rest */ +const restEndpoint = + 'https://lcd.injective.network' /* getNetworkEndpoints(Network.Mainnet).rest */ const txRestClient = new TxRestClient(restEndpoint) const txHash = await txRestClient.broadcast(txRawEip712) -/** - * Once we get the txHash, because we use the Sync mode we - * are not sure that the transaction is included in the block, - * it can happen that it's still in the mempool so we need to query +/** + * Once we get the txHash, because we use the Sync mode we + * are not sure that the transaction is included in the block, + * it can happen that it's still in the mempool so we need to query * the chain to see when the transaction will be included */ - /** This will poll querying the transaction and await for it's inclusion in the block */ +/** This will poll querying the transaction and await for it's inclusion in the block */ const response = await txRestClient.fetchTxPoll(txHash) ``` @@ -140,7 +145,7 @@ const response = await txRestClient.fetchTxPoll(txHash) Let's have a look at the whole flow (using Metamask as a signing wallet) ```ts -import { +import { MsgSend, ChainRestAuthApi, ChainRestTendermintApi, @@ -148,22 +153,24 @@ import { DEFAULT_STD_FEE, getEip712TypedData, } from '@injectivelabs/sdk-ts' -import { DEFAULT_STD_FEE, DEFAULT_BLOCK_TIMEOUT_HEIGHT } from '@injectivelabs/utils' +import { + DEFAULT_STD_FEE, + DEFAULT_BLOCK_TIMEOUT_HEIGHT, +} from '@injectivelabs/utils' import { ChainId } from '@injectivelabs/ts-types' import { Network, getNetworkEndpoints } from '@injectivelabs/networks' const injectiveAddress = 'inj1' const chainId = 'injective-1' /* ChainId.Mainnet */ -const restEndpoint = 'https://lcd.injective.network' /* getNetworkEndpoints(Network.Mainnet).rest */ +const restEndpoint = + 'https://lcd.injective.network' /* getNetworkEndpoints(Network.Mainnet).rest */ const amount = { amount: new BigNumberInBase(0.01).toWei().toFixed(), - denom: "inj", -}; + denom: 'inj', +} /** Account Details **/ -const chainRestAuthApi = new ChainRestAuthApi( - restEndpoint, -) +const chainRestAuthApi = new ChainRestAuthApi(restEndpoint) const accountDetailsResponse = await chainRestAuthApi.fetchAccount( injectiveAddress, ) @@ -171,9 +178,7 @@ const baseAccount = BaseAccount.fromRestApi(accountDetailsResponse) const accountDetails = baseAccount.toAccountDetails() /** Block Details */ -const chainRestTendermintApi = new ChainRestTendermintApi( - restEndpoint, -) +const chainRestTendermintApi = new ChainRestTendermintApi(restEndpoint) const latestBlock = await chainRestTendermintApi.fetchLatestBlock() const latestHeight = latestBlock.header.height const timeoutHeight = new BigNumberInBase(latestHeight).plus( @@ -185,7 +190,7 @@ const msg = MsgSend.fromJSON({ amount, srcInjectiveAddress: injectiveAddress, dstInjectiveAddress: injectiveAddress, -}); +}) /** EIP712 for signing on Ethereum wallets */ const eip712TypedData = getEip712TypedData({ @@ -206,10 +211,7 @@ const signature = await window.ethereum.request({ }) /** Get Public Key of the signer */ -const publicKeyHex = recoverTypedSignaturePubKey( - eip712TypedData, - signature, -) +const publicKeyHex = recoverTypedSignaturePubKey(eip712TypedData, signature) const publicKeyBase64 = hexToBase64(publicKeyHex) const { txRaw } = createTransaction({ @@ -240,8 +242,4 @@ const response = await txRestClient.fetchTxPoll(txHash) ### Example with WalletStrategy (Prepare + Sign + Broadcast) -🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 - -This part is currently under work in progress. - -🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 +Example can be found [here](https://github.com/InjectiveLabs/injective-ts/blob/862e7c30d96120947b056abffbd01b4f378984a1/packages/wallet-ts/src/broadcaster/MsgBroadcaster.ts#L166-L248). diff --git a/.gitbook/transactions/transactions-cosmos.md b/.gitbook/transactions/transactions-cosmos.md index 3846e6124..1f6c6a6ae 100644 --- a/.gitbook/transactions/transactions-cosmos.md +++ b/.gitbook/transactions/transactions-cosmos.md @@ -10,31 +10,35 @@ At this point you **can't** use some online abstractions that provide a quick wa To resolve this, we have provided functions which can prepare the `txRaw` transaction within out `@injectivelabs/sdk-ts` package. `txRaw` is the transaction interface used in Cosmos that contains details about the transaction and the signer itself. +Getting a private key from cosmos wallets is usually done by taking the current key for the chainId and accessing the pubKey from there (ex: `const key = await window.keplr.getKey(chainId)` => `const pubKey = key.publicKey`). + ```ts -import { +import { MsgSend, - ChainRestAuthApi, - ChainRestTendermintApi, BaseAccount, DEFAULT_STD_FEE, + ChainRestAuthApi, createTransaction, + ChainRestTendermintApi, } from '@injectivelabs/sdk-ts' -import { DEFAULT_STD_FEE, DEFAULT_BLOCK_TIMEOUT_HEIGHT } from '@injectivelabs/utils' +import { + DEFAULT_STD_FEE, + DEFAULT_BLOCK_TIMEOUT_HEIGHT, +} from '@injectivelabs/utils' import { ChainId } from '@injectivelabs/ts-types' import { Network, getNetworkEndpoints } from '@injectivelabs/networks' const injectiveAddress = 'inj1' const chainId = 'injective-1' /* ChainId.Mainnet */ -const restEndpoint = 'https://lcd.injective.network' /* getNetworkEndpoints(Network.Mainnet).rest */ +const restEndpoint = + 'https://lcd.injective.network' /* getNetworkEndpoints(Network.Mainnet).rest */ const amount = { amount: new BigNumberInBase(0.01).toWei().toFixed(), - denom: "inj", -}; + denom: 'inj', +} /** Account Details **/ -const chainRestAuthApi = new ChainRestAuthApi( - restEndpoint, -) +const chainRestAuthApi = new ChainRestAuthApi(restEndpoint) const accountDetailsResponse = await chainRestAuthApi.fetchAccount( injectiveAddress, ) @@ -42,9 +46,7 @@ const baseAccount = BaseAccount.fromRestApi(accountDetailsResponse) const accountDetails = baseAccount.toAccountDetails() /** Block Details */ -const chainRestTendermintApi = new ChainRestTendermintApi( - restEndpoint, -) +const chainRestTendermintApi = new ChainRestTendermintApi(restEndpoint) const latestBlock = await chainRestTendermintApi.fetchLatestBlock() const latestHeight = latestBlock.header.height const timeoutHeight = new BigNumberInBase(latestHeight).plus( @@ -56,7 +58,7 @@ const msg = MsgSend.fromJSON({ amount, srcInjectiveAddress: injectiveAddress, dstInjectiveAddress: injectiveAddress, -}); +}) /** Get the PubKey of the Signer from the Wallet/Private Key */ const pubKey = await getPubKey() @@ -82,7 +84,7 @@ import { ChainId } from '@injectivelabs/ts-types' const getKeplr = async (chainId) => { await window.keplr.enable(chainId); - + const offlineSigner = window.keplr.getOfflineSigner(chainId); const accounts = await offlineSigner.getAccounts(); const key = await window.keplr.getKey(chainId); @@ -109,19 +111,19 @@ import { ChainId } from '@injectivelabs/ts-types' import { getTxRawFromTxRawOrDirectSignResponse, TxRestClient } from '@injectivelabs/sdk-ts' import { Network, getNetworkEndpoints } from '@injectivelabs/networks' -/** - * IMPORTANT NOTE: - * If we use Keplr/Leap wallets - * after signing the transaction we get a `directSignResponse`, +/** + * IMPORTANT NOTE: + * If we use Keplr/Leap wallets + * after signing the transaction we get a `directSignResponse`, * and instead of adding the signature to the `txRaw` we create - * using the `createTransaction` function we need to append the - * signature from the `directSignResponse` to the transaction that - * got actually signed (i.e `directSignResponse.signed`) and + * using the `createTransaction` function we need to append the + * signature from the `directSignResponse` to the transaction that + * got actually signed (i.e `directSignResponse.signed`) and * the reason why is that the user can make some changes on the original - * transaction (i.e change gas limit or gas prices) and the transaction + * transaction (i.e change gas limit or gas prices) and the transaction * that get's signed and the one that gets broadcasted are not the same. */ -const directSignResponse = /* From the second step above */ +const directSignResponse = /* From the second step above */ const txRaw = getTxRawFromTxRawOrDirectSignResponse(directSignResponse) const broadcastTx = async (chainId, txRaw) => { @@ -150,10 +152,10 @@ const broadcastTx = async (chainId, txRaw) => { const txHash = await broadcastTx(ChainId.Mainnet, txRaw) -/** - * Once we get the txHash, because we use the Sync mode we - * are not sure that the transaction is included in the block, - * it can happen that it's still in the mempool so we need to query +/** + * Once we get the txHash, because we use the Sync mode we + * are not sure that the transaction is included in the block, + * it can happen that it's still in the mempool so we need to query * the chain to see when the transaction will be included */ const restEndpoint = 'https://lcd.injective.network' /* getNetworkEndpoints(Network.Mainnet).rest */ @@ -168,24 +170,28 @@ const response = await txRestClient.fetchTxPoll(txHash) Let's have a look at the whole flow (using Keplr as a signing wallet) ```ts -import { +import { MsgSend, - ChainRestAuthApi, - ChainRestTendermintApi, BaseAccount, DEFAULT_STD_FEE, + ChainRestAuthApi, createTransaction, + CosmosTxV1Beta1Tx, + ChainRestTendermintApi, } from '@injectivelabs/sdk-ts' -import { DEFAULT_STD_FEE, DEFAULT_BLOCK_TIMEOUT_HEIGHT } from '@injectivelabs/utils' +import { + DEFAULT_STD_FEE, + DEFAULT_BLOCK_TIMEOUT_HEIGHT, +} from '@injectivelabs/utils' import { ChainId } from '@injectivelabs/ts-types' import { Network, getNetworkEndpoints } from '@injectivelabs/networks' const getKeplr = async (chainId) => { - await window.keplr.enable(chainId); - - const offlineSigner = window.keplr.getOfflineSigner(chainId); - const accounts = await offlineSigner.getAccounts(); - const key = await window.keplr.getKey(chainId); + await window.keplr.enable(chainId) + + const offlineSigner = window.keplr.getOfflineSigner(chainId) + const accounts = await offlineSigner.getAccounts() + const key = await window.keplr.getKey(chainId) return { offlineSigner, accounts, key } } @@ -194,7 +200,7 @@ const broadcastTx = async (chainId, txRaw) => { const keplr = await getKeplr(ChainId.Mainnet) const result = await keplr.sendTx( chainId, - txRaw.serializeBinary(), + CosmosTxV1Beta1Tx.TxRaw.encode(txRaw).finish(), BroadcastMode.Sync, ) @@ -210,16 +216,15 @@ const broadcastTx = async (chainId, txRaw) => { const injectiveAddress = 'inj1' const chainId = 'injective-1' /* ChainId.Mainnet */ -const restEndpoint = 'https://lcd.injective.network' /* getNetworkEndpoints(Network.Mainnet).rest */ +const restEndpoint = + 'https://lcd.injective.network' /* getNetworkEndpoints(Network.Mainnet).rest */ const amount = { amount: new BigNumberInBase(0.01).toWei().toFixed(), - denom: "inj", -}; + denom: 'inj', +} /** Account Details **/ -const chainRestAuthApi = new ChainRestAuthApi( - restEndpoint, -) +const chainRestAuthApi = new ChainRestAuthApi(restEndpoint) const accountDetailsResponse = await chainRestAuthApi.fetchAccount( injectiveAddress, ) @@ -227,9 +232,7 @@ const baseAccount = BaseAccount.fromRestApi(accountDetailsResponse) const accountDetails = baseAccount.toAccountDetails() /** Block Details */ -const chainRestTendermintApi = new ChainRestTendermintApi( - restEndpoint, -) +const chainRestTendermintApi = new ChainRestTendermintApi(restEndpoint) const latestBlock = await chainRestTendermintApi.fetchLatestBlock() const latestHeight = latestBlock.header.height const timeoutHeight = new BigNumberInBase(latestHeight).plus( @@ -241,7 +244,7 @@ const msg = MsgSend.fromJSON({ amount, srcInjectiveAddress: injectiveAddress, dstInjectiveAddress: injectiveAddress, -}); +}) /** Get the PubKey of the Signer from the Wallet/Private Key */ const pubKey = await getPubKey() @@ -257,7 +260,10 @@ const { txRaw, signDoc } = createTransaction({ accountNumber: baseAccount.accountNumber, }) -const directSignResponse = await offlineSigner.signDirect(injectiveAddress, signDoc) +const directSignResponse = await offlineSigner.signDirect( + injectiveAddress, + signDoc, +) const txRaw = getTxRawFromTxRawOrDirectSignResponse(directSignResponse) const txHash = await broadcastTx(ChainId.Mainnet, txRaw) const response = await new TxRestClient(restEndpoint).fetchTxPoll(txHash) @@ -265,8 +271,4 @@ const response = await new TxRestClient(restEndpoint).fetchTxPoll(txHash) ### Example with WalletStrategy (Prepare + Sign + Broadcast) -🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 - -This part is currently under work in progress. - -🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 +Example can be found [here](https://github.com/InjectiveLabs/injective-ts/blob/862e7c30d96120947b056abffbd01b4f378984a1/packages/wallet-ts/src/broadcaster/MsgBroadcaster.ts#L301-L365). From 612c35652ad10650ef1610e639d417965c373b6f Mon Sep 17 00:00:00 2001 From: Bojan Angjelkoski Date: Fri, 13 Oct 2023 09:55:13 +0200 Subject: [PATCH 6/6] refactor: minor --- packages/sdk-ui-ts/src/services/ibc/tokens.ts | 37 ++++++++++++------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/packages/sdk-ui-ts/src/services/ibc/tokens.ts b/packages/sdk-ui-ts/src/services/ibc/tokens.ts index 240b07190..0adcfb85b 100644 --- a/packages/sdk-ui-ts/src/services/ibc/tokens.ts +++ b/packages/sdk-ui-ts/src/services/ibc/tokens.ts @@ -24,19 +24,30 @@ const TOKEN_METADATA_PATH = 'ibc/chain/injective-1/tokens' function ibcTokenMetadataToToken( ibcTokenMetadata: IbcTokenMetadata[], ): Token[] { - return ibcTokenMetadata.map((token) => ({ - name: token.name || 'Unknown', - denom: token.contractAddr || '', - logo: token.imageUrl || 'untracked.svg', - symbol: token.symbol || 'Unknown', - decimals: token.decimals || 18, - coinGeckoId: '', - tokenType: TokenType.Ibc, - tokenVerification: TokenVerification.External, - })) + return ibcTokenMetadata.map((token) => { + return { + name: token.name || 'Unknown', + denom: token.contractAddr || '', + logo: token.imageUrl || 'untracked.svg', + symbol: token.symbol || 'Unknown', + decimals: token.decimals || 18, + coinGeckoId: '', + tokenType: TokenType.Ibc, + tokenVerification: TokenVerification.External, + ibc: { + hash: (token.contractAddr || '').replace('ibc/', ''), + path: '', + channelId: '', + decimals: token.decimals || 18, + symbol: token.symbol || 'Unknown', + baseDenom: token.symbol || 'Unknown', + isNative: false, + }, + } + }) } -const fetchIbcTokens = async () => { +;(async () => { try { const response = (await ibcTokenMetadataApi.get(TOKEN_METADATA_PATH)) as { data: IbcTokenMetadata[] @@ -57,6 +68,4 @@ const fetchIbcTokens = async () => { return } -} - -fetchIbcTokens() +})()