Skip to content

Commit

Permalink
yield the receipt from the tracker generator
Browse files Browse the repository at this point in the history
  • Loading branch information
barnjamin committed Dec 28, 2023
1 parent dc90598 commit 4698ab1
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 28 deletions.
38 changes: 20 additions & 18 deletions connect/src/protocols/tokenTransfer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,11 @@ import {
WormholeTransfer,
} from "../wormholeTransfer";

type TransferProtocol = "TokenBridge" | "AutomaticTokenBridge";
type TransferVAA = TokenBridge.TransferVAA | AutomaticTokenBridge.VAA;
type TokenTransferProtocol = "TokenBridge" | "AutomaticTokenBridge";
type TokenTransferVAA = TokenBridge.TransferVAA | AutomaticTokenBridge.VAA;

export class TokenTransfer<N extends Network = Network>
implements WormholeTransfer<TransferProtocol>
implements WormholeTransfer<TokenTransferProtocol>
{
private readonly wh: Wormhole<N>;

Expand All @@ -59,7 +59,7 @@ export class TokenTransfer<N extends Network = Network>
// on the source chain (if its been completed and finalized)
vaas?: {
id: WormholeMessageId;
vaa?: TransferVAA;
vaa?: TokenTransferVAA;
}[];

private constructor(wh: Wormhole<N>, transfer: TokenTransferDetails) {
Expand Down Expand Up @@ -257,15 +257,13 @@ export class TokenTransfer<N extends Network = Network>
return redeemTxids.map(({ txid }) => txid);
}

// Async fn that produces status updates through an async generator
// AsyncGenerator fn that produces status updates through an async generator
// eventually producing a receipt
// can be called repeatedly so the receipt is updated as it moves through the
// steps of the transfer
// Note: it should be possible to call this fn as many times
// as it takes until the destination is finalized
static async *track<N extends Network>(
wh: Wormhole<N>,
receipt: TransferReceipt<TransferProtocol>,
receipt: TransferReceipt<TokenTransferProtocol>,
timeout: number = DEFAULT_TASK_TIMEOUT,
// Optional parameters to override chain context (typically for custom rpc)
_fromChain?: ChainContext<N, ChainToPlatform<typeof receipt.from>, typeof receipt.from>,
Expand All @@ -292,7 +290,7 @@ export class TokenTransfer<N extends Network = Network>
);
receipt.attestation = { id: xfermsg };
receipt.state = TransferState.SourceFinalized;
yield receipt.state;
yield receipt;
}
}

Expand All @@ -311,7 +309,7 @@ export class TokenTransfer<N extends Network = Network>
);
receipt.attestation.attestation = vaa;
receipt.state = TransferState.Attested;
yield receipt.state;
yield receipt;
}
}

Expand All @@ -325,7 +323,10 @@ export class TokenTransfer<N extends Network = Network>
receipt.attestation.id!,
leftover(start, timeout),
);
if (!txStatus) return receipt;
if (!txStatus) {
yield receipt;
return;
}

if (txStatus.globalTx?.destinationTx?.txHash) {
const { chainId, txHash } = txStatus.globalTx.destinationTx;
Expand All @@ -338,7 +339,7 @@ export class TokenTransfer<N extends Network = Network>
];

receipt.state = TransferState.DestinationFinalized;
yield receipt.state;
yield receipt;
}

// Fall back to asking the destination chain if this VAA has been redeemed
Expand All @@ -347,15 +348,16 @@ export class TokenTransfer<N extends Network = Network>
receipt.attestation.attestation &&
(await TokenTransfer.isTransferComplete(
_toChain,
receipt.attestation.attestation as TransferVAA,
receipt.attestation.attestation as TokenTransferVAA,
),
leftover(start, timeout))
) {
receipt.state = TransferState.DestinationFinalized;
yield receipt.state;
yield receipt;
}
}
return receipt;
yield receipt;
return;
}

// Static method to perform the transfer so a custom RPC may be used
Expand Down Expand Up @@ -387,7 +389,7 @@ export class TokenTransfer<N extends Network = Network>
// Static method to allow passing a custom RPC
static async redeem<N extends Network>(
toChain: ChainContext<N, Platform, Chain>,
vaa: TokenBridge.TransferVAA | AutomaticTokenBridge.VAA,
vaa: TokenTransferVAA,
signer: Signer<N, Chain>,
): Promise<TransactionId[]> {
const signerAddress = toNative(signer.chain(), signer.address());
Expand All @@ -404,7 +406,7 @@ export class TokenTransfer<N extends Network = Network>
N extends Network,
P extends Platform,
C extends PlatformToChains<P>,
>(toChain: ChainContext<N, P, C>, vaa: TransferVAA): Promise<boolean> {
>(toChain: ChainContext<N, P, C>, vaa: TokenTransferVAA): Promise<boolean> {
// TODO: converter?
if (vaa.protocolName === "AutomaticTokenBridge")
vaa = deserialize("TokenBridge:TransferWithPayload", serialize(vaa));
Expand All @@ -428,7 +430,7 @@ export class TokenTransfer<N extends Network = Network>
wh: Wormhole<N>,
key: WormholeMessageId | TxHash,
timeout?: number,
): Promise<TransferVAA> {
): Promise<TokenTransferVAA> {
const vaa =
typeof key === "string"
? await wh.getVaaByTxHash(key, TokenBridge.getTransferDiscriminator(), timeout)
Expand Down
9 changes: 6 additions & 3 deletions connect/src/wormholeTransfer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,20 +86,23 @@ export type TransferQuote = {
};

// Static methods on the Transfer protocol types
// e.g. `TokenTransfer.constructor`
export interface TransferProtocol<PN extends ProtocolName> {
isTransferComplete<N extends Network, P extends Platform, C extends PlatformToChains<P>>(
toChain: ChainContext<N, P, C>,
vaa: VAA,
): Promise<boolean>;
isAutomatic<N extends Network>(wh: Wormhole<N>, vaa: VAA): boolean;
//validateTransfer<N extends Network>(wh: Wormhole<N>, transfer: )
validateTransferDetails<N extends Network>(
wh: Wormhole<N>,
transfer: TransferRequest<PN>,
): Promise<void>;
quoteTransfer(xfer: WormholeTransfer<PN>): Promise<TransferQuote>;
getReceipt(xfer: WormholeTransfer<PN>): TransferReceipt<PN>;
track<N extends Network>(
wh: Wormhole<N>,
xfer: WormholeTransfer<PN>,
timeout: number,
): AsyncGenerator<TransferState, TransferReceipt<PN>, unknown>;
): AsyncGenerator<TransferReceipt<PN>, unknown, unknown>;
}

// WormholeTransfer abstracts the process and state transitions
Expand Down
19 changes: 13 additions & 6 deletions examples/src/helpers/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
Wormhole,
api,
tasks,
DEFAULT_TASK_TIMEOUT,
} from "@wormhole-foundation/connect-sdk";

// Importing from src so we dont have to rebuild to see debug stuff in signer
Expand Down Expand Up @@ -70,12 +71,18 @@ export async function getStuff<
};
}

export async function waitLog(wh: Wormhole<Network>, xfer: TokenTransfer) {
const it = TokenTransfer.track(wh, TokenTransfer.getReceipt(xfer));
let res;
for (res = await it.next(); !res.done; res = await it.next())
console.log("Current Transfer State: ", TransferState[res.value as TransferState]);
return res.value;
export async function waitLog<N extends Network = Network>(
wh: Wormhole<N>,
xfer: TokenTransfer<N>,
tag: string = "WaitLog",
timeout: number = DEFAULT_TASK_TIMEOUT,
) {
const tracker = TokenTransfer.track(wh, TokenTransfer.getReceipt(xfer), timeout);
let receipt;
for await (receipt of tracker) {
console.log(`${tag}: Current trasfer state: `, TransferState[receipt.state]);
}
return receipt;
}

// Note: This API may change but it is currently the best place to pull
Expand Down
2 changes: 1 addition & 1 deletion examples/src/tokenBridge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ import "@wormhole-foundation/connect-sdk-solana-tokenbridge";
// of the token
// On the destination side, a wrapped version of the token will be minted
// to the address specified in the transfer VAA
const automatic = true;
const automatic = false;

// The automatic relayer has the ability to deliver some native gas funds to the destination account
// The amount specified for native gas will be swapped for the native gas token according
Expand Down

0 comments on commit 4698ab1

Please sign in to comment.