diff --git a/sdk/js/CHANGELOG.md b/sdk/js/CHANGELOG.md index e2ac8fa8d..63e653715 100644 --- a/sdk/js/CHANGELOG.md +++ b/sdk/js/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## 0.4.5 + +### Changed + +Fix hex/Uint8Array to native Terra 2 for 20-byte addresses + ## 0.4.4 ### Added diff --git a/sdk/js/package.json b/sdk/js/package.json index d2a80ba67..1644302f2 100644 --- a/sdk/js/package.json +++ b/sdk/js/package.json @@ -1,6 +1,6 @@ { "name": "@certusone/wormhole-sdk", - "version": "0.4.4", + "version": "0.4.5", "description": "SDK for interacting with Wormhole", "homepage": "https://wormholenetwork.com", "main": "./lib/cjs/index.js", diff --git a/sdk/js/src/utils/array.test.ts b/sdk/js/src/utils/array.test.ts new file mode 100644 index 000000000..b060e6170 --- /dev/null +++ b/sdk/js/src/utils/array.test.ts @@ -0,0 +1,20 @@ +import { zeroPad } from "ethers/lib/utils"; +import { canonicalAddress } from "../terra"; +import { tryUint8ArrayToNative } from "./array"; + +test("terra address conversion", () => { + const human = "terra1x46rqay4d3cssq8gxxvqz8xt6nwlz4td20k38v"; + const canonical = canonicalAddress(human); + const lpadCanonical = zeroPad(canonical, 32); + const nativeClassic = tryUint8ArrayToNative(lpadCanonical, "terra"); + expect(nativeClassic).toBe(human); + const native2 = tryUint8ArrayToNative(lpadCanonical, "terra2"); + expect(native2).toBe(human); + // terra 2 contracts are 32 bytes + const humanContract = + "terra14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9ssrc8au"; + const canonicalContract = canonicalAddress(humanContract); + const nativeContract = tryUint8ArrayToNative(canonicalContract, "terra2"); + expect(nativeContract).toBe(nativeContract); + // TODO: native to hex is wrong, which we should correct +}); diff --git a/sdk/js/src/utils/array.ts b/sdk/js/src/utils/array.ts index f80250e68..03aca5878 100644 --- a/sdk/js/src/utils/array.ts +++ b/sdk/js/src/utils/array.ts @@ -41,6 +41,9 @@ import { */ export const isHexNativeTerra = (h: string): boolean => h.startsWith("01"); +const isLikely20ByteTerra = (h: string): boolean => + h.startsWith("000000000000000000000000"); + export const nativeTerraHexToDenom = (h: string): string => Buffer.from(stripZeros(hexToUint8Array(h.substr(2)))).toString("ascii"); @@ -72,7 +75,11 @@ export const tryUint8ArrayToNative = ( if (isHexNativeTerra(h)) { return nativeTerraHexToDenom(h); } else { - return humanAddress(chainId === CHAIN_ID_TERRA2 ? a : a.slice(-20)); // terra classic expects 20 bytes, not 32 + if (chainId === CHAIN_ID_TERRA2 && !isLikely20ByteTerra(h)) { + // terra 2 has 32 byte addresses for contracts and 20 for wallets + return humanAddress(a); + } + return humanAddress(a.slice(-20)); } } else if (chainId === CHAIN_ID_ALGORAND) { return uint8ArrayToNativeStringAlgorand(a);