@wormhole-foundation/sdk-cosmwasm-tokenbridge
Version:
SDK for EVM chains, used in conjunction with @wormhole-foundation/sdk
239 lines • 10.6 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CosmwasmTokenBridge = void 0;
const sdk_connect_1 = require("@wormhole-foundation/sdk-connect");
const sdk_cosmwasm_1 = require("@wormhole-foundation/sdk-cosmwasm");
require("@wormhole-foundation/sdk-cosmwasm-core");
class CosmwasmTokenBridge {
network;
chain;
rpc;
contracts;
tokenBridge;
translator;
constructor(network, chain, rpc, contracts) {
this.network = network;
this.chain = chain;
this.rpc = rpc;
this.contracts = contracts;
const tokenBridgeAddress = this.contracts.tokenBridge;
if (!tokenBridgeAddress)
throw new Error(`Wormhole Token Bridge contract for domain ${chain} not found`);
this.tokenBridge = tokenBridgeAddress;
// May be undefined, thats ok
this.translator = this.contracts.translator;
// But it cannot be an empty string (misconfiguration)
if (this.translator !== undefined && this.translator === "")
throw new Error("Translator address may be undefined but not empty string");
}
static async fromRpc(rpc, config) {
const [network, chain] = await sdk_cosmwasm_1.CosmwasmPlatform.chainFromRpc(rpc);
const conf = config[chain];
if (conf.network !== network)
throw new Error(`Network mismatch: ${conf.network} != ${network}`);
return new CosmwasmTokenBridge(network, chain, rpc, config[chain].contracts);
}
async isWrappedAsset(token) {
try {
await this.getOriginalAsset(token);
return true;
}
catch { }
return false;
}
async hasWrappedAsset(token) {
try {
await this.getWrappedAsset(token);
return true;
}
catch { }
return false;
}
async getWrappedAsset(token) {
if (token.chain === this.chain)
throw new Error(`Expected foreign chain, got ${token.chain}`);
if ((0, sdk_connect_1.isNative)(token.address))
throw new Error("Native asset cannot be a wrapped asset");
const base64Addr = sdk_connect_1.encoding.b64.encode(token.address.toUniversalAddress().toUint8Array());
const { address } = await this.rpc.queryContractSmart(this.tokenBridge, {
wrapped_registry: {
chain: (0, sdk_connect_1.toChainId)(token.chain),
address: base64Addr,
},
});
return (0, sdk_connect_1.toNative)(this.chain, address);
}
async getOriginalAsset(token) {
let wrappedAddress = new sdk_cosmwasm_1.CosmwasmAddress(token);
if (wrappedAddress.denomType === "factory")
wrappedAddress = sdk_cosmwasm_1.Gateway.factoryToCw20(wrappedAddress);
const response = await this.rpc.queryContractSmart(wrappedAddress.toString(), {
wrapped_asset_info: {},
});
const origChain = (0, sdk_connect_1.toChain)(response.asset_chain);
const origAddress = sdk_connect_1.encoding.b64.decode(response.asset_address);
return {
chain: origChain,
address: new sdk_connect_1.UniversalAddress(new Uint8Array(origAddress)),
};
}
async getTokenUniversalAddress(token) {
return new sdk_cosmwasm_1.CosmwasmAddress(token).toUniversalAddress();
}
async getTokenNativeAddress(originChain, token) {
return new sdk_cosmwasm_1.CosmwasmAddress(token).toNative();
}
async isTransferCompleted(vaa) {
const data = sdk_connect_1.encoding.b64.encode((0, sdk_connect_1.serialize)(vaa));
const result = await this.rpc.queryContractSmart(this.tokenBridge, {
is_vaa_redeemed: { vaa: data },
});
return result.is_redeemed;
}
async *createAttestation(token, payer) {
if (!payer)
throw new Error("Payer required to create attestation");
const tokenStr = new sdk_cosmwasm_1.CosmwasmAddress(token).toString();
const payerStr = new sdk_cosmwasm_1.CosmwasmAddress(payer).toString();
// TODO nonce?
const nonce = 0;
const assetInfo = (0, sdk_connect_1.isNative)(token)
? {
native_token: {
denom: sdk_cosmwasm_1.CosmwasmPlatform.getNativeDenom(this.network, this.chain),
},
}
: {
token: { contract_addr: tokenStr },
};
yield this.createUnsignedTx({
msgs: [
(0, sdk_cosmwasm_1.buildExecuteMsg)(payerStr, this.tokenBridge, {
create_asset_meta: { asset_info: assetInfo, nonce },
}),
],
fee: (0, sdk_cosmwasm_1.computeFee)(this.network, this.chain),
memo: "Wormhole - Create Attestation",
}, "TokenBridge.createAttestation");
}
async *submitAttestation(vaa, payer) {
if (!payer)
throw new Error("Payer required to submit attestation");
const payerStr = new sdk_cosmwasm_1.CosmwasmAddress(payer).toString();
yield this.createUnsignedTx({
msgs: [
(0, sdk_cosmwasm_1.buildExecuteMsg)(payerStr, this.tokenBridge, {
submit_vaa: { data: (0, sdk_connect_1.serialize)(vaa) },
}),
],
fee: (0, sdk_cosmwasm_1.computeFee)(this.network, this.chain),
memo: "Wormhole - Submit Attestation",
}, "TokenBridge.submitAttestation");
}
async *transfer(sender, recipient, token, amount, payload) {
const nonce = Math.round(Math.random() * 100000);
const relayerFee = "0";
const recipientChainId = (0, sdk_connect_1.toChainId)(recipient.chain);
// TODO: do we need to use the _native_ address for cosmos chains?
const encodedRecipient = sdk_connect_1.encoding.b64.encode(recipient.address.toUniversalAddress().toUint8Array());
const denom = sdk_cosmwasm_1.CosmwasmPlatform.getNativeDenom(this.network, this.chain);
const isNativeToken = (0, sdk_connect_1.isNative)(token);
let tokenAddress = isNativeToken ? denom : token.toString();
if (tokenAddress.startsWith("factory"))
tokenAddress = sdk_cosmwasm_1.Gateway.factoryToCw20(new sdk_cosmwasm_1.CosmwasmAddress(tokenAddress)).toString();
const senderAddress = new sdk_cosmwasm_1.CosmwasmAddress(sender).toString();
const mk_initiate_transfer = (info) => {
const common = {
asset: {
amount: amount.toString(),
info,
},
recipient_chain: recipientChainId,
recipient: encodedRecipient,
fee: relayerFee,
nonce: nonce,
};
return payload
? {
initiate_transfer_with_payload: { ...common, payload: sdk_connect_1.encoding.b64.encode(payload) },
}
: {
initiate_transfer: common,
};
};
// this.createConvertAndTransferMessage(
// senderAddress,
// targetChain,
// targetAddress,
// relayerFee,
// { denom: Gateway.cw20ToFactory(token), amount },
// )
if (isNativeToken) {
const msgs = [
(0, sdk_cosmwasm_1.buildExecuteMsg)(senderAddress, this.tokenBridge, { deposit_tokens: {} }, [
{ amount: amount.toString(), denom: tokenAddress },
]),
(0, sdk_cosmwasm_1.buildExecuteMsg)(senderAddress, this.tokenBridge, mk_initiate_transfer({
native_token: { denom: tokenAddress },
})),
];
yield this.createUnsignedTx({
msgs,
fee: (0, sdk_cosmwasm_1.computeFee)(this.network, this.chain),
memo: "Wormhole - Initiate Native Transfer",
}, "TokenBridge.transferNative");
}
else {
const msgs = [
(0, sdk_cosmwasm_1.buildExecuteMsg)(senderAddress, tokenAddress, {
increase_allowance: {
spender: this.tokenBridge,
amount: amount.toString(),
expires: { never: {} },
},
}),
(0, sdk_cosmwasm_1.buildExecuteMsg)(senderAddress, this.tokenBridge, mk_initiate_transfer({
token: { contract_addr: tokenAddress },
}), [{ amount: amount.toString(), denom: tokenAddress }]),
];
yield this.createUnsignedTx({
msgs,
fee: (0, sdk_cosmwasm_1.computeFee)(this.network, this.chain),
memo: "Wormhole - Initiate Transfer",
}, "TokenBridge.transfer");
}
}
async *redeem(sender, vaa, unwrapNative = true) {
// TODO: unwrapNative
const data = sdk_connect_1.encoding.b64.encode((0, sdk_connect_1.serialize)(vaa));
const senderAddress = new sdk_cosmwasm_1.CosmwasmAddress(sender).toString();
const toTranslator = this.translator &&
new sdk_cosmwasm_1.CosmwasmAddress(this.translator).toUniversalAddress().equals(vaa.payload.to.address);
const msg = toTranslator
? (0, sdk_cosmwasm_1.buildExecuteMsg)(senderAddress, this.translator, {
complete_transfer_and_convert: {
vaa: data,
},
})
: (0, sdk_cosmwasm_1.buildExecuteMsg)(senderAddress, this.tokenBridge, {
submit_vaa: { data },
});
yield this.createUnsignedTx({
msgs: [msg],
fee: (0, sdk_cosmwasm_1.computeFee)(this.network, this.chain),
memo: "Wormhole - Complete Transfer",
}, "TokenBridge.redeem");
return;
}
async parseTransactionDetails(txid) {
throw new Error("Not implemented");
}
async getWrappedNative() {
return (0, sdk_connect_1.toNative)(this.chain, sdk_cosmwasm_1.CosmwasmPlatform.getNativeDenom(this.network, this.chain));
}
createUnsignedTx(txReq, description, parallelizable = false) {
return new sdk_cosmwasm_1.CosmwasmUnsignedTransaction(txReq, this.network, this.chain, description, parallelizable);
}
}
exports.CosmwasmTokenBridge = CosmwasmTokenBridge;
//# sourceMappingURL=tokenBridge.js.map