@wormhole-foundation/sdk-cosmwasm
Version:
SDK for EVM chains, used in conjunction with @wormhole-foundation/sdk
212 lines (200 loc) • 7.47 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CosmwasmAddress = void 0;
const sdk_connect_1 = require("@wormhole-foundation/sdk-connect");
const constants_js_1 = require("./constants.js");
const types_js_1 = require("./types.js");
/*
Cosmos Addresses
-----
There are at least 5 types of addresses in Cosmos:
Native Denom
ex: "uatom"
address = [] // 0 bytes
domain = undefined
denom = "uatom"
denomType = "native"
Contract Address
ex: "wormhole1ctnjk7an90lz5wjfvr3cf6x984a8cjnv8dpmztmlpcq4xteaa2xs9pwmzk"
address = [0x...] // 32 bytes
domain = "wormhole"
denom = undefined
denomType = undefined
Account Address
ex: "cosmos1hsk6jryyqjfhp5dhc55tc9jtckygx0eph6dd02"
address = [0x...] // 20 bytes
domain = "cosmos"
denom = undefined
denomType = undefined
IBC Denom
ex: IBC/BAEAC83736444C09656FBE666FB625974FCCDEE566EB700EBFD2642C5F6CF13A
address = [0x...] // 32 bytes
domain = undefined
denom = undefined
denomType = "IBC"
Factory Address
ex: "factory/inj17vytdwqczqz72j65saukplrktd4gyfme5agf6c/avax"
address = [0x...] 20 bytes
domain = "inj"
denom = "avax"
denomType = "factory"
Transfer Denom
ex: transfer/channel-486/factory/wormhole1ctnjk7an90lz5wjfvr3cf6x984a8cjnv8dpmztmlpcq4xteaa2xs9pwmzk/6vxRV62YN1CTZeQM5ZfvCZDCVA4nLhtZcLxziYa7xYqb
address = [0x...] 32 bytes
domain = "wormhole"
denom = "6vxRV62YN1CTZeQM5ZfvCZDCVA4nLhtZcLxziYa7xYqb"
denomType = "transfer/channel-486/factory"
*/
// Factory type addresses may have hex or b64 or bech32 encoded addresses
function tryDecode(data) {
try {
const decoded = sdk_connect_1.encoding.bech32.decodeToBytes(data);
return { data: decoded.bytes, prefix: decoded.prefix };
}
catch { }
try {
return { data: sdk_connect_1.encoding.hex.decode(data) };
}
catch { }
try {
return { data: sdk_connect_1.encoding.b64.decode(data) };
}
catch { }
throw new Error(`Cannot decode: ${data}`);
}
class CosmwasmAddress {
static contractAddressByteSize = 32;
static accountAddressByteSize = 20;
static platform = types_js_1._platform;
// the actual bytes of the address
address;
// The domain is the prefix for the address, like "cosmos" or "ibc"
domain;
// The denom is the token name, like "uatom" or "usdc"
denom;
// The denomType is "native", "ibc", or "factory"
denomType;
constructor(address) {
if (CosmwasmAddress.instanceof(address)) {
const a = address;
this.address = a.address;
this.domain = a.domain;
this.denom = a.denom;
this.denomType = a.denomType;
return;
}
if (typeof address === "string") {
// A native denom like "uatom"
if (address.length <= 8) {
this.address = new Uint8Array(0);
this.denom = address;
this.denomType = "native";
return;
}
if (address.indexOf("/") !== -1) {
// A denom address like "ibc/..." or "factory/..." or "transfer/channel-${id}/factory/..."
const chunks = address.split("/");
// It's a `transfer/...` denom
if (chunks.length >= 3) {
// Address will be second from the last
const { data, prefix } = tryDecode(chunks[chunks.length - 2]);
this.address = data;
this.domain = prefix;
this.denom = chunks[chunks.length - 1];
this.denomType = chunks.slice(0, chunks.length - 2).join("/");
}
else {
const { data } = tryDecode(chunks[1]);
this.address = data;
this.denomType = chunks[0];
}
}
else {
// should be a contract or account address by now
if (!CosmwasmAddress.isValidAddress(address))
throw new Error(`Invalid Cosmwasm address: ${address}`);
const { bytes: data, prefix } = sdk_connect_1.encoding.bech32.decodeToBytes(address);
this.address = data;
this.domain = prefix;
}
}
else if (address instanceof Uint8Array) {
this.address = address;
}
else if (sdk_connect_1.UniversalAddress.instanceof(address)) {
this.address = address.toUint8Array();
}
else
throw new Error(`Invalid Cosmwasm address ${address}`);
if (!CosmwasmAddress.validAddressLength(this.address)) {
throw new Error("Expected 20 or 32 bytes address");
}
}
unwrap() {
return this.toString();
}
toString() {
// Coin address
if (this.denomType !== undefined) {
// native asset denom
if (this.denomType === "native")
return this.denom;
// ibc/hex
if (this.denomType === "ibc") {
// NOTE: this is case sensitive, should be `ibc` not `IBC`
return `${this.denomType.toLowerCase()}/${sdk_connect_1.encoding.hex.encode(this.address).toUpperCase()}`;
}
// ?/factory/address/denom
return `${this.denomType}/${CosmwasmAddress.encode(this.domain, this.address)}/${this.denom}`;
}
// contract or account address
return CosmwasmAddress.encode(this.domain, this.address);
}
toNative() {
return this;
}
toUint8Array() {
return this.address;
}
toUniversalAddress() {
const buff = new Uint8Array(sdk_connect_1.UniversalAddress.byteSize);
buff.set(this.address, sdk_connect_1.UniversalAddress.byteSize - this.address.length);
return new sdk_connect_1.UniversalAddress(buff);
}
setChain(chain) {
// @ts-expect-error -- readonly
this.domain = constants_js_1.chainToAddressPrefix.get(chain);
}
static isValidAddress(address) {
try {
const maybe = sdk_connect_1.encoding.bech32.decodeToBytes(address);
return CosmwasmAddress.validAddressLength(maybe.bytes);
}
catch { }
return false;
}
static encode(prefix, address) {
return sdk_connect_1.encoding.bech32.encode(prefix, sdk_connect_1.encoding.bech32.toWords(address));
}
static validAddressLength(address) {
if (address.length !== CosmwasmAddress.contractAddressByteSize &&
address.length !== CosmwasmAddress.accountAddressByteSize)
throw new Error(`Invalid Cosmwasm address, expected ${CosmwasmAddress.contractAddressByteSize} ` +
`or ${CosmwasmAddress.accountAddressByteSize} bytes but got ${address.length}`);
return true;
}
static instanceof(address) {
return address.constructor.platform === CosmwasmAddress.platform;
}
equals(other) {
if (CosmwasmAddress.instanceof(other)) {
return this.toString() === other.toString();
}
else {
return other.equals(this.toUniversalAddress());
}
}
}
exports.CosmwasmAddress = CosmwasmAddress;
(0, sdk_connect_1.registerNative)(types_js_1._platform, CosmwasmAddress);
//# sourceMappingURL=address.js.map