From fd4fc1898cca7e822976e291d3bcee93f5275db3 Mon Sep 17 00:00:00 2001 From: J M Rossy Date: Fri, 15 Dec 2023 12:21:17 -0500 Subject: [PATCH] Upgrade Viem & fix neutron chainmetadata (#3049) ### Description - Upgrade Viem and wagmi chains versions - Add optional RestUrl field to ChainMetadata - Set rest url for Neutron - Add simple deepCopy function Prerequisite for https://github.com/hyperlane-xyz/hyperlane-warp-ui-template/issues/80 ### Backward compatibility Yes ### Testing Tested in Warp UI --- .changeset/great-readers-fry.md | 9 + typescript/sdk/package.json | 4 +- typescript/sdk/src/consts/chainMetadata.ts | 1 + typescript/sdk/src/core/HyperlaneCore.ts | 11 +- .../sdk/src/metadata/chainMetadataTypes.ts | 4 + typescript/utils/index.ts | 1 + typescript/utils/src/addresses.ts | 24 ++- typescript/utils/src/objects.ts | 4 + yarn.lock | 161 ++++++++---------- 9 files changed, 117 insertions(+), 102 deletions(-) create mode 100644 .changeset/great-readers-fry.md diff --git a/.changeset/great-readers-fry.md b/.changeset/great-readers-fry.md new file mode 100644 index 000000000..701aa8172 --- /dev/null +++ b/.changeset/great-readers-fry.md @@ -0,0 +1,9 @@ +--- +'@hyperlane-xyz/utils': patch +'@hyperlane-xyz/sdk': patch +--- + +- Upgrade Viem to 1.20.0 +- Add optional restUrls field to ChainMetadata +- Add deepCopy util function +- Add support for cosmos factory token addresses diff --git a/typescript/sdk/package.json b/typescript/sdk/package.json index 78cc14ce7..4d2d6bbf4 100644 --- a/typescript/sdk/package.json +++ b/typescript/sdk/package.json @@ -11,14 +11,14 @@ "@solana/web3.js": "^1.78.0", "@types/coingecko-api": "^1.0.10", "@types/debug": "^4.1.7", - "@wagmi/chains": "^0.2.6", + "@wagmi/chains": "^1.8.0", "bignumber.js": "^9.1.1", "coingecko-api": "^1.0.10", "cosmjs-types": "^0.9.0", "cross-fetch": "^3.1.5", "debug": "^4.3.4", "ethers": "^5.7.2", - "viem": "^1.3.1", + "viem": "^1.20.0", "zod": "^3.21.2" }, "devDependencies": { diff --git a/typescript/sdk/src/consts/chainMetadata.ts b/typescript/sdk/src/consts/chainMetadata.ts index 11728d5ac..ac38c51f8 100644 --- a/typescript/sdk/src/consts/chainMetadata.ts +++ b/typescript/sdk/src/consts/chainMetadata.ts @@ -617,6 +617,7 @@ export const neutron: ChainMetadata = { symbol: 'NTRN', }, protocol: ProtocolType.Cosmos, + restUrls: [{ http: 'grpc-kralum.neutron-1.neutron.org:80' }], rpcUrls: [{ http: 'https://rpc-kralum.neutron-1.neutron.org' }], slip44: 118, }; diff --git a/typescript/sdk/src/core/HyperlaneCore.ts b/typescript/sdk/src/core/HyperlaneCore.ts index 00f3f9113..78d922428 100644 --- a/typescript/sdk/src/core/HyperlaneCore.ts +++ b/typescript/sdk/src/core/HyperlaneCore.ts @@ -1,4 +1,5 @@ import { ethers } from 'ethers'; +import type { TransactionReceipt as ViemTxReceipt } from 'viem'; import { Mailbox__factory } from '@hyperlane-xyz/core'; import { @@ -119,7 +120,7 @@ export class HyperlaneCore extends HyperlaneApp { } waitForMessageProcessing( - sourceTx: ethers.ContractReceipt, + sourceTx: ethers.ContractReceipt | ViemTxReceipt, ): Promise { const messages = HyperlaneCore.getDispatchedMessages(sourceTx); return Promise.all(messages.map((msg) => this.waitForProcessReceipt(msg))); @@ -127,7 +128,7 @@ export class HyperlaneCore extends HyperlaneApp { // TODO consider renaming this, all the waitForMessage* methods are confusing async waitForMessageProcessed( - sourceTx: ethers.ContractReceipt, + sourceTx: ethers.ContractReceipt | ViemTxReceipt, delay?: number, maxAttempts?: number, ): Promise { @@ -146,12 +147,14 @@ export class HyperlaneCore extends HyperlaneApp { } // Redundant with static method but keeping for backwards compatibility - getDispatchedMessages(sourceTx: ethers.ContractReceipt): DispatchedMessage[] { + getDispatchedMessages( + sourceTx: ethers.ContractReceipt | ViemTxReceipt, + ): DispatchedMessage[] { return HyperlaneCore.getDispatchedMessages(sourceTx); } static getDispatchedMessages( - sourceTx: ethers.ContractReceipt, + sourceTx: ethers.ContractReceipt | ViemTxReceipt, ): DispatchedMessage[] { const mailbox = Mailbox__factory.createInterface(); const dispatchLogs = sourceTx.logs diff --git a/typescript/sdk/src/metadata/chainMetadataTypes.ts b/typescript/sdk/src/metadata/chainMetadataTypes.ts index 9418beb6d..1ed7ecdb2 100644 --- a/typescript/sdk/src/metadata/chainMetadataTypes.ts +++ b/typescript/sdk/src/metadata/chainMetadataTypes.ts @@ -107,6 +107,10 @@ export const ChainMetadataSchemaObject = z.object({ .array(RpcUrlSchema) .nonempty() .describe('The list of RPC endpoints for interacting with the chain.'), + restUrls: z + .array(RpcUrlSchema) + .describe('For cosmos chains only, a list of Rest API URLs') + .optional(), blockExplorers: z .array( z.object({ diff --git a/typescript/utils/index.ts b/typescript/utils/index.ts index 4730a417f..f1ea44d95 100644 --- a/typescript/utils/index.ts +++ b/typescript/utils/index.ts @@ -84,6 +84,7 @@ export { export { ValueOf, arrayToObject, + deepCopy, deepEquals, invertKeysAndValues, isObject, diff --git a/typescript/utils/src/addresses.ts b/typescript/utils/src/addresses.ts index 131c12c1c..5ff42ab37 100644 --- a/typescript/utils/src/addresses.ts +++ b/typescript/utils/src/addresses.ts @@ -6,9 +6,16 @@ import { Address, HexString, ProtocolType } from './types'; const EVM_ADDRESS_REGEX = /^0x[a-fA-F0-9]{40}$/; const SEALEVEL_ADDRESS_REGEX = /^[a-zA-Z0-9]{36,44}$/; -const COSMOS_ADDRESS_REGEX = - /^[a-z]{1,10}1[qpzry9x8gf2tvdw0s3jn54khce6mua7l]{38,58}$/; // Bech32 -export const IBC_DENOM_REGEX = /^ibc\/([A-Fa-f0-9]{64})$/; + +// https://github.com/cosmos/cosmos-sdk/blob/84c33215658131d87daf3c629e909e12ed9370fa/types/coin.go#L601C17-L601C44 +const COSMOS_DENOM_PATTERN = `[a-zA-Z][a-zA-Z0-9]{2,127}`; +// https://en.bitcoin.it/wiki/BIP_0173 +const BECH32_ADDRESS_PATTERN = `[a-zA-Z]{1,83}1[qpzry9x8gf2tvdw0s3jn54khce6mua7l]{38,58}`; +const COSMOS_ADDRESS_REGEX = new RegExp(`^${BECH32_ADDRESS_PATTERN}$`); +const IBC_DENOM_REGEX = new RegExp(`^ibc/([A-Fa-f0-9]{64})$`); +const COSMOS_FACTORY_TOKEN_REGEX = new RegExp( + `^factory/(${BECH32_ADDRESS_PATTERN})/${COSMOS_DENOM_PATTERN}$`, +); const EVM_TX_HASH_REGEX = /^0x([A-Fa-f0-9]{64})$/; const SEALEVEL_TX_HASH_REGEX = /^[a-zA-Z1-9]{88}$/; @@ -26,7 +33,11 @@ export function isAddressSealevel(address: Address) { } export function isAddressCosmos(address: Address) { - return COSMOS_ADDRESS_REGEX.test(address) || IBC_DENOM_REGEX.test(address); + return ( + COSMOS_ADDRESS_REGEX.test(address) || + IBC_DENOM_REGEX.test(address) || + COSMOS_FACTORY_TOKEN_REGEX.test(address) + ); } export function getAddressProtocolType(address: Address) { @@ -79,7 +90,10 @@ export function isValidAddressSealevel(address: Address) { export function isValidAddressCosmos(address: Address) { try { const isValid = - address && (IBC_DENOM_REGEX.test(address) || fromBech32(address)); + address && + (IBC_DENOM_REGEX.test(address) || + COSMOS_FACTORY_TOKEN_REGEX.test(address) || + fromBech32(address)); return !!isValid; } catch (error) { return false; diff --git a/typescript/utils/src/objects.ts b/typescript/utils/src/objects.ts index a99e7ff1d..bff85958b 100644 --- a/typescript/utils/src/objects.ts +++ b/typescript/utils/src/objects.ts @@ -6,6 +6,10 @@ export function deepEquals(v1: any, v2: any) { return JSON.stringify(v1) === JSON.stringify(v2); } +export function deepCopy(v: any) { + return JSON.parse(JSON.stringify(v)); +} + export type ValueOf = T[keyof T]; export function objMapEntries< diff --git a/yarn.lock b/yarn.lock index e723fcc3d..1ce0f5421 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5,10 +5,10 @@ __metadata: version: 8 cacheKey: 10 -"@adraffy/ens-normalize@npm:1.9.0": - version: 1.9.0 - resolution: "@adraffy/ens-normalize@npm:1.9.0" - checksum: 5257bbb45796720386a250ec2747f1c93b8fccd7063839ccda4aeb1b97ebec81caf5b435252dae1842c37175fe2e0ddcb89039f4ec1a4934fa4c6901a7f4992b +"@adraffy/ens-normalize@npm:1.10.0": + version: 1.10.0 + resolution: "@adraffy/ens-normalize@npm:1.10.0" + checksum: 5cdb5d2a9c9f8c0a71a7bb830967da0069cae1f1235cd41ae11147e4000f368f6958386e622cd4d52bf45c1ed3f8275056b387cba28902b83354e40ff323ecde languageName: node linkType: hard @@ -4412,7 +4412,7 @@ __metadata: "@types/sinon": "npm:^17.0.1" "@types/sinon-chai": "npm:^3.2.12" "@types/ws": "npm:^8.5.5" - "@wagmi/chains": "npm:^0.2.6" + "@wagmi/chains": "npm:^1.8.0" bignumber.js: "npm:^9.1.1" chai: "npm:^4.3.6" coingecko-api: "npm:^1.0.10" @@ -4429,7 +4429,7 @@ __metadata: sinon: "npm:^13.0.2" ts-node: "npm:^10.8.0" typescript: "npm:5.1.6" - viem: "npm:^1.3.1" + viem: "npm:^1.20.0" zod: "npm:^3.21.2" peerDependencies: "@ethersproject/abi": "*" @@ -4819,12 +4819,12 @@ __metadata: languageName: node linkType: hard -"@noble/curves@npm:1.0.0, @noble/curves@npm:~1.0.0": - version: 1.0.0 - resolution: "@noble/curves@npm:1.0.0" +"@noble/curves@npm:1.2.0, @noble/curves@npm:~1.2.0": + version: 1.2.0 + resolution: "@noble/curves@npm:1.2.0" dependencies: - "@noble/hashes": "npm:1.3.0" - checksum: 6db884e03b3f6c773317bcf4611bf1d9adb8084eab0bf6158407cc998c9c5dcb0560741bdd0aaca9c4393c9e8a3dcd7592b4148a6cfd561d0a00addb77a6129f + "@noble/hashes": "npm:1.3.2" + checksum: 94e02e9571a9fd42a3263362451849d2f54405cb3ce9fa7c45bc6b9b36dcd7d1d20e2e1e14cfded24937a13d82f1e60eefc4d7a14982ce0bc219a9fc0f51d1f9 languageName: node linkType: hard @@ -4844,13 +4844,6 @@ __metadata: languageName: node linkType: hard -"@noble/hashes@npm:1.3.0": - version: 1.3.0 - resolution: "@noble/hashes@npm:1.3.0" - checksum: 4680a71941c06ac897cc9eab9d229717d5af1147cea5e8cd4942190c817426ad3173ded750d897f58d764b869f9347d4fc3f6b3c16574541ac81906efa9ddc36 - languageName: node - linkType: hard - "@noble/hashes@npm:1.3.1, @noble/hashes@npm:^1.3.0, @noble/hashes@npm:~1.3.0": version: 1.3.1 resolution: "@noble/hashes@npm:1.3.1" @@ -4858,13 +4851,20 @@ __metadata: languageName: node linkType: hard -"@noble/hashes@npm:^1, @noble/hashes@npm:^1.0.0, @noble/hashes@npm:^1.3.1": +"@noble/hashes@npm:1.3.2, @noble/hashes@npm:^1, @noble/hashes@npm:^1.0.0, @noble/hashes@npm:^1.3.1": version: 1.3.2 resolution: "@noble/hashes@npm:1.3.2" checksum: 685f59d2d44d88e738114b71011d343a9f7dce9dfb0a121f1489132f9247baa60bc985e5ec6f3213d114fbd1e1168e7294644e46cbd0ce2eba37994f28eeb51b languageName: node linkType: hard +"@noble/hashes@npm:~1.3.2": + version: 1.3.3 + resolution: "@noble/hashes@npm:1.3.3" + checksum: 1025ddde4d24630e95c0818e63d2d54ee131b980fe113312d17ed7468bc18f54486ac86c907685759f8a7e13c2f9b9e83ec7b67d1cc20836f36b5e4a65bb102d + languageName: node + linkType: hard + "@noble/secp256k1@npm:1.5.5, @noble/secp256k1@npm:~1.5.2": version: 1.5.5 resolution: "@noble/secp256k1@npm:1.5.5" @@ -5452,6 +5452,13 @@ __metadata: languageName: node linkType: hard +"@scure/base@npm:~1.1.2": + version: 1.1.4 + resolution: "@scure/base@npm:1.1.4" + checksum: e735792dc5555f9d11b93fbaffbcf65177621a60d25d54d84439155611ee98b5f6fb631ca06ef0c57a65bc4e40277331b7364e96cf7f164908bec98b546f3442 + languageName: node + linkType: hard + "@scure/bip32@npm:1.0.1": version: 1.0.1 resolution: "@scure/bip32@npm:1.0.1" @@ -5463,14 +5470,14 @@ __metadata: languageName: node linkType: hard -"@scure/bip32@npm:1.3.0": - version: 1.3.0 - resolution: "@scure/bip32@npm:1.3.0" +"@scure/bip32@npm:1.3.2": + version: 1.3.2 + resolution: "@scure/bip32@npm:1.3.2" dependencies: - "@noble/curves": "npm:~1.0.0" - "@noble/hashes": "npm:~1.3.0" - "@scure/base": "npm:~1.1.0" - checksum: 1fabcc7f2215910b35980bfc455c03fc4ae7f848efed066fe3867960a8dfceb6141c932496434fc2cfbf385d270ff9efdfce2571992e4584103f82e45ac2103f + "@noble/curves": "npm:~1.2.0" + "@noble/hashes": "npm:~1.3.2" + "@scure/base": "npm:~1.1.2" + checksum: b90da28dfe75519496a85c97e77c9443734873910f32b8557762910a5c4e642290a462b0ed14fa42e0efed6acb9a7f6155ad5cb5d38d4ff87eb2de4760eb32a4 languageName: node linkType: hard @@ -5484,13 +5491,13 @@ __metadata: languageName: node linkType: hard -"@scure/bip39@npm:1.2.0": - version: 1.2.0 - resolution: "@scure/bip39@npm:1.2.0" +"@scure/bip39@npm:1.2.1": + version: 1.2.1 + resolution: "@scure/bip39@npm:1.2.1" dependencies: "@noble/hashes": "npm:~1.3.0" "@scure/base": "npm:~1.1.0" - checksum: 2a260eefea0b2658c5d3b2cb982479ef650552c3007e57f667b445943c79717eb923c1a104a664b4873bc210aeb59859bf890c3e7b47fb51ed5b94dc96f75105 + checksum: 2ea368bbed34d6b1701c20683bf465e147f231a9e37e639b8c82f585d6f978bb0f3855fca7ceff04954ae248b3e313f5d322d0210614fb7acb402739415aaf31 languageName: node linkType: hard @@ -6431,27 +6438,15 @@ __metadata: languageName: node linkType: hard -"@wagmi/chains@npm:1.6.0": - version: 1.6.0 - resolution: "@wagmi/chains@npm:1.6.0" +"@wagmi/chains@npm:^1.8.0": + version: 1.8.0 + resolution: "@wagmi/chains@npm:1.8.0" peerDependencies: typescript: ">=5.0.4" peerDependenciesMeta: typescript: optional: true - checksum: 809954d65e0d32cfbf079f7f3df1ff6596d1da96187e177597bcaf0fa71532e7416186f3f7e94efe45cf529b1709a57b08e0e06b67b5529223221a6b82f1dc78 - languageName: node - linkType: hard - -"@wagmi/chains@npm:^0.2.6": - version: 0.2.6 - resolution: "@wagmi/chains@npm:0.2.6" - peerDependencies: - typescript: ">=4.9.4" - peerDependenciesMeta: - typescript: - optional: true - checksum: b56c6ec78fc077795b58757123bf04f387ecc7c3ee2088f9192de9d8e4e7b7f07bfaa8761ef8ecd180bb0a6276cf6827ce4b5958eb8d26b1ee7a90038d595ac6 + checksum: 8248419554a90c0d514acfc46f3a6f2090a282ff546b2488705e81fcdfaf197590e67a1fc62539383b4dd22ccafe9f16018cadad27acee098dc9d87b82f173e4 languageName: node linkType: hard @@ -6481,9 +6476,9 @@ __metadata: languageName: node linkType: hard -"abitype@npm:0.9.3": - version: 0.9.3 - resolution: "abitype@npm:0.9.3" +"abitype@npm:0.9.8": + version: 0.9.8 + resolution: "abitype@npm:0.9.8" peerDependencies: typescript: ">=5.0.4" zod: ^3 >=3.19.1 @@ -6492,7 +6487,7 @@ __metadata: optional: true zod: optional: true - checksum: 6a3f71b76b5d9b1fcda2796b46fdb89d3deaa7e89f64e530dff373ae50a29fd1b34a53bc4291ffc6b097baf400baaa5f374f5c2b53987c223e6dad38f379d348 + checksum: 90940804839b1b65cb5b427d934db9c1cc899157d6091f281b1ce94d9c0c08b1ae946ab43e984e70c031e94c49355f6677475a7242ec60cae5457c074dcd40f9 languageName: node linkType: hard @@ -11708,21 +11703,21 @@ __metadata: languageName: node linkType: hard -"isomorphic-ws@npm:5.0.0": - version: 5.0.0 - resolution: "isomorphic-ws@npm:5.0.0" +"isomorphic-ws@npm:^4.0.1": + version: 4.0.1 + resolution: "isomorphic-ws@npm:4.0.1" peerDependencies: ws: "*" - checksum: e20eb2aee09ba96247465fda40c6d22c1153394c0144fa34fe6609f341af4c8c564f60ea3ba762335a7a9c306809349f9b863c8beedf2beea09b299834ad5398 + checksum: d7190eadefdc28bdb93d67b5f0c603385aaf87724fa2974abb382ac1ec9756ed2cfb27065cbe76122879c2d452e2982bc4314317f3d6c737ddda6c047328771a languageName: node linkType: hard -"isomorphic-ws@npm:^4.0.1": - version: 4.0.1 - resolution: "isomorphic-ws@npm:4.0.1" +"isows@npm:1.0.3": + version: 1.0.3 + resolution: "isows@npm:1.0.3" peerDependencies: ws: "*" - checksum: d7190eadefdc28bdb93d67b5f0c603385aaf87724fa2974abb382ac1ec9756ed2cfb27065cbe76122879c2d452e2982bc4314317f3d6c737ddda6c047328771a + checksum: 9cacd5cf59f67deb51e825580cd445ab1725ecb05a67c704050383fb772856f3cd5e7da8ad08f5a3bd2823680d77d099459d0c6a7037972a74d6429af61af440 languageName: node linkType: hard @@ -17086,25 +17081,24 @@ __metadata: languageName: node linkType: hard -"viem@npm:^1.3.1": - version: 1.3.1 - resolution: "viem@npm:1.3.1" - dependencies: - "@adraffy/ens-normalize": "npm:1.9.0" - "@noble/curves": "npm:1.0.0" - "@noble/hashes": "npm:1.3.0" - "@scure/bip32": "npm:1.3.0" - "@scure/bip39": "npm:1.2.0" - "@wagmi/chains": "npm:1.6.0" - abitype: "npm:0.9.3" - isomorphic-ws: "npm:5.0.0" - ws: "npm:8.12.0" +"viem@npm:^1.20.0": + version: 1.20.0 + resolution: "viem@npm:1.20.0" + dependencies: + "@adraffy/ens-normalize": "npm:1.10.0" + "@noble/curves": "npm:1.2.0" + "@noble/hashes": "npm:1.3.2" + "@scure/bip32": "npm:1.3.2" + "@scure/bip39": "npm:1.2.1" + abitype: "npm:0.9.8" + isows: "npm:1.0.3" + ws: "npm:8.13.0" peerDependencies: typescript: ">=5.0.4" peerDependenciesMeta: typescript: optional: true - checksum: 073edf64453dd8bbce7bc6c6ac6a0281d6acc1e4ae7a770a01dba86c86e5a28ea5b466bb2f86833f3a822e699067ff23e1b6da1a272c8b9b7f1b7eb56eecc552 + checksum: f6f232e1b75085b2088e842a44d3e574afd3e603420cf65181d6fb0dec7942d0c4f4d3cdae8f7a43ddb9942dcb185443b1d5b7daec8a009a3cbab9436bea2164 languageName: node linkType: hard @@ -17737,9 +17731,9 @@ __metadata: languageName: node linkType: hard -"ws@npm:8.12.0": - version: 8.12.0 - resolution: "ws@npm:8.12.0" +"ws@npm:8.13.0, ws@npm:^8.5.0": + version: 8.13.0 + resolution: "ws@npm:8.13.0" peerDependencies: bufferutil: ^4.0.1 utf-8-validate: ">=5.0.2" @@ -17748,7 +17742,7 @@ __metadata: optional: true utf-8-validate: optional: true - checksum: 325fbcf6bbed07350b82d7a5bdb43e8a4e81512973241c656c2119a37883a74fe49e7cac09646f9bfc28c517cd63f4111c78f5898bcdd25a3ec2cc4e59375331 + checksum: 1769532b6fdab9ff659f0b17810e7501831d34ecca23fd179ee64091dd93a51f42c59f6c7bb4c7a384b6c229aca8076fb312aa35626257c18081511ef62a161d languageName: node linkType: hard @@ -17793,21 +17787,6 @@ __metadata: languageName: node linkType: hard -"ws@npm:^8.5.0": - version: 8.13.0 - resolution: "ws@npm:8.13.0" - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: ">=5.0.2" - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - checksum: 1769532b6fdab9ff659f0b17810e7501831d34ecca23fd179ee64091dd93a51f42c59f6c7bb4c7a384b6c229aca8076fb312aa35626257c18081511ef62a161d - languageName: node - linkType: hard - "xhr-request-promise@npm:^0.1.2": version: 0.1.3 resolution: "xhr-request-promise@npm:0.1.3"