clients/js: Make address handling nicer
commit-id:1d3ce65d
This commit is contained in:
parent
3641682c63
commit
96560a98f8
|
@ -3,6 +3,7 @@ import yargs from "yargs";
|
||||||
|
|
||||||
import { hideBin } from "yargs/helpers";
|
import { hideBin } from "yargs/helpers";
|
||||||
|
|
||||||
|
import { Bech32, fromBech32, toHex } from "@cosmjs/encoding";
|
||||||
import { isTerraChain, assertEVMChain, CONTRACTS, setDefaultWasm } from "@certusone/wormhole-sdk";
|
import { isTerraChain, assertEVMChain, CONTRACTS, setDefaultWasm } from "@certusone/wormhole-sdk";
|
||||||
import { execute_governance_solana } from "./solana";
|
import { execute_governance_solana } from "./solana";
|
||||||
import { execute_governance_evm, getImplementation, hijack_evm, query_contract_evm, setStorageAt } from "./evm";
|
import { execute_governance_evm, getImplementation, hijack_evm, query_contract_evm, setStorageAt } from "./evm";
|
||||||
|
@ -19,6 +20,7 @@ import {
|
||||||
} from "@certusone/wormhole-sdk";
|
} from "@certusone/wormhole-sdk";
|
||||||
import { ethers } from "ethers";
|
import { ethers } from "ethers";
|
||||||
import { NETWORKS } from "./networks";
|
import { NETWORKS } from "./networks";
|
||||||
|
import base58 from "bs58";
|
||||||
|
|
||||||
setDefaultWasm("node");
|
setDefaultWasm("node");
|
||||||
|
|
||||||
|
@ -98,10 +100,7 @@ yargs(hideBin(process.argv))
|
||||||
type: "RegisterChain",
|
type: "RegisterChain",
|
||||||
chain: 0,
|
chain: 0,
|
||||||
emitterChain: toChainId(argv["chain"]),
|
emitterChain: toChainId(argv["chain"]),
|
||||||
emitterAddress: Buffer.from(
|
emitterAddress: parseAddress(argv["chain"], argv["contract-address"]),
|
||||||
argv["contract-address"].padStart(64, "0"),
|
|
||||||
"hex"
|
|
||||||
),
|
|
||||||
};
|
};
|
||||||
let v = makeVAA(
|
let v = makeVAA(
|
||||||
GOVERNANCE_CHAIN,
|
GOVERNANCE_CHAIN,
|
||||||
|
@ -149,10 +148,7 @@ yargs(hideBin(process.argv))
|
||||||
module,
|
module,
|
||||||
type: "ContractUpgrade",
|
type: "ContractUpgrade",
|
||||||
chain: toChainId(argv["chain"]),
|
chain: toChainId(argv["chain"]),
|
||||||
address: Buffer.from(
|
address: parseCodeAddress(argv["chain"], argv["contract-address"]),
|
||||||
evm_address(argv["contract-address"]),
|
|
||||||
"hex"
|
|
||||||
),
|
|
||||||
};
|
};
|
||||||
let v = makeVAA(
|
let v = makeVAA(
|
||||||
GOVERNANCE_CHAIN,
|
GOVERNANCE_CHAIN,
|
||||||
|
@ -183,8 +179,9 @@ yargs(hideBin(process.argv))
|
||||||
async (argv) => {
|
async (argv) => {
|
||||||
const buf = Buffer.from(String(argv.vaa), "hex");
|
const buf = Buffer.from(String(argv.vaa), "hex");
|
||||||
const parsed_vaa = vaa.parse(buf);
|
const parsed_vaa = vaa.parse(buf);
|
||||||
console.log(parsed_vaa);
|
let parsed_vaa_with_digest = parsed_vaa;
|
||||||
console.log("Digest:", vaa.vaaDigest(parsed_vaa))
|
parsed_vaa_with_digest['digest'] = vaa.vaaDigest(parsed_vaa);
|
||||||
|
console.log(parsed_vaa_with_digest);
|
||||||
})
|
})
|
||||||
.command("recover <digest> <signature>", "Recover an address from a signature", (yargs) => {
|
.command("recover <digest> <signature>", "Recover an address from a signature", (yargs) => {
|
||||||
return yargs
|
return yargs
|
||||||
|
@ -522,3 +519,29 @@ function hex(x: string): string {
|
||||||
function evm_address(x: string): string {
|
function evm_address(x: string): string {
|
||||||
return hex(x).substring(2).padStart(64, "0")
|
return hex(x).substring(2).padStart(64, "0")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function parseAddress(chain: ChainName, address: string): string {
|
||||||
|
if (chain === "unset") {
|
||||||
|
throw Error("Chain unset")
|
||||||
|
} else if (isEVMChain(chain)) {
|
||||||
|
return "0x" + evm_address(address)
|
||||||
|
} else if (isTerraChain(chain)) {
|
||||||
|
return "0x" + toHex(fromBech32(address).data).padStart(64, "0")
|
||||||
|
} else if (chain === "solana") {
|
||||||
|
return "0x" + toHex(base58.decode(address)).padStart(64, "0")
|
||||||
|
} else if (chain === "algorand") {
|
||||||
|
throw Error("Algorand is not supported yet")
|
||||||
|
} else if (chain === "near") {
|
||||||
|
throw Error("NEAR is not supported yet")
|
||||||
|
} else {
|
||||||
|
impossible(chain)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseCodeAddress(chain: ChainName, address: string): string {
|
||||||
|
if (isTerraChain(chain)) {
|
||||||
|
return "0x" + parseInt(address, 10).toString(16).padStart(64, "0")
|
||||||
|
} else {
|
||||||
|
return parseAddress(chain, address)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@celo-tools/celo-ethers-wrapper": "^0.1.0",
|
"@celo-tools/celo-ethers-wrapper": "^0.1.0",
|
||||||
"@certusone/wormhole-sdk": "^0.4.4",
|
"@certusone/wormhole-sdk": "^0.4.4",
|
||||||
|
"@cosmjs/encoding": "^0.26.2",
|
||||||
"@solana/web3.js": "^1.22.0",
|
"@solana/web3.js": "^1.22.0",
|
||||||
"@terra-money/terra.js": "^3.1.3",
|
"@terra-money/terra.js": "^3.1.3",
|
||||||
"axios": "^0.24.0",
|
"axios": "^0.24.0",
|
||||||
|
@ -563,6 +564,16 @@
|
||||||
"resolved": "https://registry.npmjs.org/bech32/-/bech32-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/bech32/-/bech32-2.0.0.tgz",
|
||||||
"integrity": "sha512-LcknSilhIGatDAsY1ak2I8VtGaHNhgMSYVxFrGLXv+xLHytaKZKcaUJJUE7qmBr7h33o5YQwP55pMI0xmkpJwg=="
|
"integrity": "sha512-LcknSilhIGatDAsY1ak2I8VtGaHNhgMSYVxFrGLXv+xLHytaKZKcaUJJUE7qmBr7h33o5YQwP55pMI0xmkpJwg=="
|
||||||
},
|
},
|
||||||
|
"node_modules/@cosmjs/encoding": {
|
||||||
|
"version": "0.26.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/@cosmjs/encoding/-/encoding-0.26.8.tgz",
|
||||||
|
"integrity": "sha512-rsqdeCHPmSXSjwE6pzbsx/drxIZKPiIxza4hYsGCaVsxrFZmgOFNmvWgtuIOIEXPS/ZoyST9XU9aMpkaYzLEVQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"base64-js": "^1.3.0",
|
||||||
|
"bech32": "^1.1.4",
|
||||||
|
"readonly-date": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@cspotcode/source-map-consumer": {
|
"node_modules/@cspotcode/source-map-consumer": {
|
||||||
"version": "0.8.0",
|
"version": "0.8.0",
|
||||||
"resolved": "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz",
|
"resolved": "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz",
|
||||||
|
@ -8834,6 +8845,11 @@
|
||||||
"node": ">= 6"
|
"node": ">= 6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/readonly-date": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/readonly-date/-/readonly-date-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-tMKIV7hlk0h4mO3JTmmVuIlJVXjKk3Sep9Bf5OH0O+758ruuVkUy2J9SttDLm91IEX/WHlXPSpxMGjPj4beMIQ=="
|
||||||
|
},
|
||||||
"node_modules/regenerator-runtime": {
|
"node_modules/regenerator-runtime": {
|
||||||
"version": "0.13.9",
|
"version": "0.13.9",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
|
@ -10956,6 +10972,16 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@cosmjs/encoding": {
|
||||||
|
"version": "0.26.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/@cosmjs/encoding/-/encoding-0.26.8.tgz",
|
||||||
|
"integrity": "sha512-rsqdeCHPmSXSjwE6pzbsx/drxIZKPiIxza4hYsGCaVsxrFZmgOFNmvWgtuIOIEXPS/ZoyST9XU9aMpkaYzLEVQ==",
|
||||||
|
"requires": {
|
||||||
|
"base64-js": "^1.3.0",
|
||||||
|
"bech32": "^1.1.4",
|
||||||
|
"readonly-date": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@cspotcode/source-map-consumer": {
|
"@cspotcode/source-map-consumer": {
|
||||||
"version": "0.8.0",
|
"version": "0.8.0",
|
||||||
"resolved": "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz",
|
"resolved": "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz",
|
||||||
|
@ -17284,6 +17310,11 @@
|
||||||
"util-deprecate": "^1.0.1"
|
"util-deprecate": "^1.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"readonly-date": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/readonly-date/-/readonly-date-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-tMKIV7hlk0h4mO3JTmmVuIlJVXjKk3Sep9Bf5OH0O+758ruuVkUy2J9SttDLm91IEX/WHlXPSpxMGjPj4beMIQ=="
|
||||||
|
},
|
||||||
"regenerator-runtime": {
|
"regenerator-runtime": {
|
||||||
"version": "0.13.9"
|
"version": "0.13.9"
|
||||||
},
|
},
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
"@celo-tools/celo-ethers-wrapper": "^0.1.0",
|
"@celo-tools/celo-ethers-wrapper": "^0.1.0",
|
||||||
"@certusone/wormhole-sdk": "^0.4.4",
|
"@certusone/wormhole-sdk": "^0.4.4",
|
||||||
"@solana/web3.js": "^1.22.0",
|
"@solana/web3.js": "^1.22.0",
|
||||||
|
"@cosmjs/encoding": "^0.26.2",
|
||||||
"@terra-money/terra.js": "^3.1.3",
|
"@terra-money/terra.js": "^3.1.3",
|
||||||
"axios": "^0.24.0",
|
"axios": "^0.24.0",
|
||||||
"binary-parser": "^2.0.2",
|
"binary-parser": "^2.0.2",
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { Parser } from "binary-parser"
|
import { Parser } from "binary-parser"
|
||||||
import { ethers } from "ethers"
|
import { BigNumber, ethers } from "ethers"
|
||||||
import { solidityKeccak256 } from "ethers/lib/utils"
|
import { solidityKeccak256 } from "ethers/lib/utils"
|
||||||
import * as elliptic from "elliptic"
|
import * as elliptic from "elliptic"
|
||||||
|
|
||||||
|
@ -124,7 +124,7 @@ const vaaParser = new Parser()
|
||||||
.array("emitterAddress", {
|
.array("emitterAddress", {
|
||||||
type: "uint8",
|
type: "uint8",
|
||||||
lengthInBytes: 32,
|
lengthInBytes: 32,
|
||||||
formatter: arr => Buffer.from(arr).toString("hex")
|
formatter: arr => "0x" + Buffer.from(arr).toString("hex")
|
||||||
})
|
})
|
||||||
.uint64("sequence")
|
.uint64("sequence")
|
||||||
.uint8("consistencyLevel")
|
.uint8("consistencyLevel")
|
||||||
|
@ -149,7 +149,7 @@ export function serialiseVAA(vaa: VAA<Payload>) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function vaaDigest(vaa: VAA<Payload>) {
|
export function vaaDigest(vaa: VAA<Payload>) {
|
||||||
return solidityKeccak256(["bytes"], [solidityKeccak256(["bytes"], ["0x" + vaaBody(vaa)])])
|
return solidityKeccak256(["bytes"], [solidityKeccak256(["bytes"], ["0x" + vaaBody(vaa)])])
|
||||||
}
|
}
|
||||||
|
|
||||||
function vaaBody(vaa: VAA<Payload>) {
|
function vaaBody(vaa: VAA<Payload>) {
|
||||||
|
@ -182,7 +182,7 @@ function vaaBody(vaa: VAA<Payload>) {
|
||||||
encode("uint32", vaa.timestamp),
|
encode("uint32", vaa.timestamp),
|
||||||
encode("uint32", vaa.nonce),
|
encode("uint32", vaa.nonce),
|
||||||
encode("uint16", vaa.emitterChain),
|
encode("uint16", vaa.emitterChain),
|
||||||
encode("bytes32", Buffer.from(vaa.emitterAddress, "hex")),
|
encode("bytes32", hex(vaa.emitterAddress)),
|
||||||
encode("uint64", vaa.sequence),
|
encode("uint64", vaa.sequence),
|
||||||
encode("uint8", vaa.consistencyLevel),
|
encode("uint8", vaa.consistencyLevel),
|
||||||
payload_str
|
payload_str
|
||||||
|
@ -258,7 +258,7 @@ const guardianSetUpgradeParser: P<GuardianSetUpgrade> = new P(new Parser()
|
||||||
|
|
||||||
function serialiseGuardianSetUpgrade(payload: GuardianSetUpgrade): string {
|
function serialiseGuardianSetUpgrade(payload: GuardianSetUpgrade): string {
|
||||||
const body = [
|
const body = [
|
||||||
encode("bytes32", Buffer.from(Buffer.from(payload.module).toString("hex").padStart(64, "0"), "hex")),
|
encode("bytes32", encodeString(payload.module)),
|
||||||
encode("uint8", 2),
|
encode("uint8", 2),
|
||||||
encode("uint16", payload.chain),
|
encode("uint16", payload.chain),
|
||||||
encode("uint32", payload.newGuardianSetIndex),
|
encode("uint32", payload.newGuardianSetIndex),
|
||||||
|
@ -275,7 +275,7 @@ export interface CoreContractUpgrade {
|
||||||
module: "Core"
|
module: "Core"
|
||||||
type: "ContractUpgrade"
|
type: "ContractUpgrade"
|
||||||
chain: number
|
chain: number
|
||||||
address: Uint8Array
|
address: string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse a core contract upgrade payload
|
// Parse a core contract upgrade payload
|
||||||
|
@ -296,7 +296,7 @@ const coreContractUpgradeParser: P<CoreContractUpgrade> =
|
||||||
.array("address", {
|
.array("address", {
|
||||||
type: "uint8",
|
type: "uint8",
|
||||||
lengthInBytes: 32,
|
lengthInBytes: 32,
|
||||||
// formatter: (arr) => Buffer.from(arr).toString("hex")
|
formatter: (arr) => "0x" + Buffer.from(arr).toString("hex")
|
||||||
})
|
})
|
||||||
.string("end", {
|
.string("end", {
|
||||||
greedy: true,
|
greedy: true,
|
||||||
|
@ -317,7 +317,7 @@ export interface PortalContractUpgrade<Module extends "NFTBridge" | "TokenBridge
|
||||||
module: Module
|
module: Module
|
||||||
type: "ContractUpgrade"
|
type: "ContractUpgrade"
|
||||||
chain: number
|
chain: number
|
||||||
address: Uint8Array
|
address: string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse a portal contract upgrade payload
|
// Parse a portal contract upgrade payload
|
||||||
|
@ -338,7 +338,7 @@ function portalContractUpgradeParser<Module extends "NFTBridge" | "TokenBridge">
|
||||||
.array("address", {
|
.array("address", {
|
||||||
type: "uint8",
|
type: "uint8",
|
||||||
lengthInBytes: 32,
|
lengthInBytes: 32,
|
||||||
// formatter: (arr) => Buffer.from(arr).toString("hex")
|
formatter: (arr) => "0x" + Buffer.from(arr).toString("hex")
|
||||||
})
|
})
|
||||||
.string("end", {
|
.string("end", {
|
||||||
greedy: true,
|
greedy: true,
|
||||||
|
@ -364,7 +364,7 @@ export interface PortalRegisterChain<Module extends "NFTBridge" | "TokenBridge">
|
||||||
type: "RegisterChain"
|
type: "RegisterChain"
|
||||||
chain: number
|
chain: number
|
||||||
emitterChain: number
|
emitterChain: number
|
||||||
emitterAddress: Uint8Array
|
emitterAddress: string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse a portal chain registration payload
|
// Parse a portal chain registration payload
|
||||||
|
@ -386,13 +386,13 @@ function portalRegisterChainParser<Module extends "NFTBridge" | "TokenBridge">(m
|
||||||
.array("emitterAddress", {
|
.array("emitterAddress", {
|
||||||
type: "uint8",
|
type: "uint8",
|
||||||
lengthInBytes: 32,
|
lengthInBytes: 32,
|
||||||
// formatter: (arr) => Buffer.from(arr).toString("hex")
|
formatter: (arr) => "0x" + Buffer.from(arr).toString("hex")
|
||||||
})
|
})
|
||||||
.string("end", {
|
.string("end", {
|
||||||
greedy: true,
|
greedy: true,
|
||||||
assert: str => str === ""
|
assert: str => str === ""
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function serialisePortalRegisterChain<Module extends "NFTBridge" | "TokenBridge">(payload: PortalRegisterChain<Module>): string {
|
function serialisePortalRegisterChain<Module extends "NFTBridge" | "TokenBridge">(payload: PortalRegisterChain<Module>): string {
|
||||||
|
@ -457,3 +457,8 @@ export function encode(type: Encoding, val: any): string {
|
||||||
export function encodeString(str: string): Buffer {
|
export function encodeString(str: string): Buffer {
|
||||||
return Buffer.from(Buffer.from(str).toString("hex").padStart(64, "0"), "hex")
|
return Buffer.from(Buffer.from(str).toString("hex").padStart(64, "0"), "hex")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Turn hex string with potentially missing 0x prefix into Buffer
|
||||||
|
function hex(x: string): Buffer {
|
||||||
|
return Buffer.from(ethers.utils.hexlify(x, { allowMissingPrefix: true }).substring(2), "hex")
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue