UNPKG

@nomad-xyz/sdk-bridge

Version:
253 lines 9.56 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.TransferMessage = exports.BridgeMessage = exports.parseBody = void 0; const bignumber_1 = require("@ethersproject/bignumber"); const bytes_1 = require("@ethersproject/bytes"); const ethers_1 = require("ethers"); const sdk_1 = require("@nomad-xyz/sdk"); const ACTION_LEN = { identifier: 1, tokenId: 36, transfer: 97, }; function parseAction(buf) { // Transfer if (buf.length === ACTION_LEN.transfer) { // trim identifer const actionType = buf[0]; buf = buf.slice(ACTION_LEN.identifier); return { type: 'transfer', to: (0, bytes_1.hexlify)(buf.slice(0, 32)), amount: bignumber_1.BigNumber.from((0, bytes_1.hexlify)(buf.slice(32, 64))), detailsHash: (0, bytes_1.hexlify)(buf.slice(64)), allowFast: actionType === 4, }; } throw new Error('Bad action'); } function parseBody(messageBody) { const buf = (0, bytes_1.arrayify)(messageBody); const tokenId = buf.slice(0, 36); const token = { domain: Buffer.from(tokenId).readUInt32BE(0), id: (0, bytes_1.hexlify)(tokenId.slice(4, 36)), }; const action = parseAction(buf.slice(36)); const parsedMessage = { action, token, }; return parsedMessage; } exports.parseBody = parseBody; /** * The BridgeMessage extends {@link nomadMessage} with Bridge-specific * functionality. */ class BridgeMessage extends sdk_1.NomadMessage { /** * @hideconstructor */ constructor(context, dispatch, token, callerKnowsWhatTheyAreDoing, _backend) { if (!callerKnowsWhatTheyAreDoing) { throw new Error('Use `fromReceipt` to instantiate'); } super(context, dispatch, _backend); const fromBridge = context.mustGetBridge(this.message.from); const toBridge = context.mustGetBridge(this.message.destination); this.fromBridge = fromBridge; this.toBridge = toBridge; this.token = token; } get backend() { const backend = this._backend || this.context._backend; if (!backend) { throw new Error(`No backend in the context`); } return backend; } async getReceived() { return await this.backend.receivedTx(this.messageHash); } async getSender() { return await this.backend.sender(this.messageHash); } static async bridgeFirstFromBackend(context, transactionHash) { const m = await this.baseFirstFromBackend(context, transactionHash); const bm = BridgeMessage.fromNomadMessage(context, m, context._backend); return bm; } static async bridgeFromMessageHash(context, messageHash) { const m = await this.baseFromMessageHash(context, messageHash); const bm = BridgeMessage.fromNomadMessage(context, m, context._backend); return bm; } /** * Attempt to instantiate a BridgeMessage from an existing * {@link nomadMessage} * * @param context The {@link NomadContext} to use. * @param nomadMessage The existing nomadMessage * @returns A Bridge message * @throws if the message cannot be parsed as a bridge message */ static fromNomadMessage(context, nomadMessage, _backend) { const parsedMessageBody = parseBody(nomadMessage.message.body); return new TransferMessage(context, nomadMessage.dispatch, parsedMessageBody, _backend || context._backend); } /** * Attempt to instantiate some BridgeMessages from a transaction receipt * * @param context The {@link NomadContext} to use. * @param receipt The receipt * @returns an array of {@link BridgeMessage} objects * @throws if any message cannot be parsed as a bridge message */ static async fromReceipt(context, receipt, _backend) { const nomadMessages = await sdk_1.NomadMessage.baseFromReceipt(context, receipt); const bridgeMessages = []; for (const nomadMessage of nomadMessages) { try { const bridgeMessage = BridgeMessage.fromNomadMessage(context, nomadMessage, _backend); bridgeMessages.push(bridgeMessage); } catch (e) { // catch error if nomadMessage isn't a BridgeMessage } } return bridgeMessages; } /** * Attempt to instantiate EXACTLY one BridgeMessage from a transaction receipt * * @param context The {@link BridgeContext} to use. * @param receipt The receipt * @returns an array of {@link BridgeMessage} objects * @throws if any message cannot be parsed as a bridge message, or if there * is not EXACTLY 1 BridgeMessage in the receipt */ static async singleFromReceipt(context, receipt, _backend) { const messages = await BridgeMessage.fromReceipt(context, receipt, _backend); if (messages.length !== 1) { throw new Error('Expected single Dispatch in transaction'); } return messages[0]; } /** * Attempt to instantiate some BridgeMessages from a transaction hash by * retrieving and parsing the receipt. * * @param context The {@link NomadContext} to use. * @param nameOrDomain the domain on which the receipt was logged * @param transactionHash the transaction hash on the origin chain * @returns an array of {@link BridgeMessage} objects * @throws if any message cannot be parsed as a bridge message */ static async fromTransactionHash(context, nameOrDomain, transactionHash, _backend) { const provider = context.mustGetProvider(nameOrDomain); const receipt = await provider.getTransactionReceipt(transactionHash); if (!receipt) { throw new Error(`No receipt for ${transactionHash} on ${nameOrDomain}`); } return BridgeMessage.fromReceipt(context, receipt, _backend); } /** * Attempt to instantiate EXACTLY one BridgeMessages from a transaction hash * by retrieving and parsing the receipt. * * @param context The {@link NomadContext} to use. * @param nameOrDomain the domain on which the receipt was logged * @param transactionHash the transaction hash on the origin chain * @returns an array of {@link BridgeMessage} objects * @throws if any message cannot be parsed as a bridge message, or if there is * not EXACTLY one such message */ static async singleFromTransactionHash(context, nameOrDomain, transactionHash, _backend) { const provider = context.mustGetProvider(nameOrDomain); const receipt = await provider.getTransactionReceipt(transactionHash); if (!receipt) { throw new Error(`No receipt for ${transactionHash} on ${nameOrDomain}`); } return BridgeMessage.singleFromReceipt(context, receipt, _backend); } /** * Resolves the asset that is being transfered * * WARNING: do not hold references to these contract, as they will not be * reconnected in the event the chain connection changes. * * @returns The resolved token information. */ async asset() { return await this.context.resolveRepresentations(this.token); } /** * Resolves an interface for the asset that is being transfered on the chain * FROM WHICH it is being transferred * * WARNING: do not hold references to this contract, as it will not be * reconnected in the event the chain connection changes. * * @returns The resolved token interface. */ async assetAtOrigin() { return (await this.asset()).tokens.get(this.origin); } /** * Resolves an interface for the asset that is being transfered on the chain * TO WHICH it is being transferred * * WARNING: do not hold references to this contract, as it will not be * reconnected in the event the chain connection changes. * * @returns The resolved token interface. */ async assetAtDestination() { return (await this.asset()).tokens.get(this.destination); } } exports.BridgeMessage = BridgeMessage; /** * A TransferMessage extends the {@link BridgeMessage} with transfer-specific * functionality. */ class TransferMessage extends BridgeMessage { constructor(context, dispatch, parsed, _backend) { super(context, dispatch, parsed.token, true, _backend); this.action = parsed.action; } /** * Check if the transfer has been prefilled using the fast liquidity system. * * @returns true if the transfer has been prefilled. Else false. */ async currentlyPrefilled() { const bridge = this.context.mustGetBridge(this.destination); const lpAddress = await bridge.bridgeRouter.liquidityProvider(this.prefillId); if (lpAddress !== ethers_1.ethers.constants.AddressZero) { return true; } return false; } /** * The amount of tokens being transferred (in the smallest unit) */ get amount() { return this.action.amount; } /** * The identifier for the recipient of the tokens */ get to() { return this.action.to; } /** * The ID used for prefilling this transfer message. */ get prefillId() { return this.bodyHash; } } exports.TransferMessage = TransferMessage; //# sourceMappingURL=BridgeMessage.js.map