@@ -86,15 +86,28 @@ const initResult = await toNearKitTransaction(near, initTx).send()
8686After the transfer is initialized, you must call ` signTransfer ` to trigger MPC signing:
8787
8888``` typescript
89- // Extract the transfer ID from the InitTransferEvent in the logs
90- const initEvent = parseInitTransferEvent (initResult )
89+ import { ChainKind } from " @omni-bridge/core"
90+ import type { InitTransferEvent } from " @omni-bridge/near"
91+
92+ // Parse the InitTransferEvent from NEAR logs
93+ const initEventLog = initResult .receipts_outcome
94+ .flatMap ((r ) => r .outcome .logs )
95+ .find ((log ) => log .includes (" InitTransferEvent" ))
96+
97+ if (! initEventLog ) throw new Error (" InitTransferEvent not found in logs" )
98+ const initEvent: InitTransferEvent = JSON .parse (initEventLog ).InitTransferEvent
9199
92100const signTx = nearBuilder .buildSignTransfer (
93101 {
94- origin_chain: " Near" ,
95- origin_nonce: initEvent .nonce ,
102+ origin_chain: ChainKind .Near ,
103+ origin_nonce: BigInt (initEvent .transfer_message .origin_nonce ),
104+ },
105+ signerId , // fee recipient
106+ {
107+ fee: initEvent .transfer_message .fee .fee ,
108+ native_fee: initEvent .transfer_message .fee .native_fee ,
96109 },
97- signerId
110+ signerId ,
98111)
99112
100113const signResult = await toNearKitTransaction (near , signTx ).send ()
@@ -105,24 +118,46 @@ const signResult = await toNearKitTransaction(near, signTx).send()
105118Parse the ` SignTransferEvent ` from the sign transaction logs and finalize on EVM:
106119
107120``` typescript
108- import { createEvmBuilder } from " @omni-bridge/evm"
121+ import { createEvmBuilder , type TransferPayload } from " @omni-bridge/evm"
109122import { ChainKind } from " @omni-bridge/core"
110- import { MPCSignature } from " @omni-bridge/near"
123+ import { MPCSignature , type SignTransferEvent } from " @omni-bridge/near"
111124
112125const evm = createEvmBuilder ({ network: " mainnet" , chain: ChainKind .Eth })
113126
114- // Parse SignTransferEvent from signResult logs
115- const signEvent = parseSignTransferEvent (signResult )
127+ // Parse SignTransferEvent from NEAR logs
128+ const signEventLog = signResult .receipts_outcome
129+ .flatMap ((r ) => r .outcome .logs )
130+ .find ((log ) => log .includes (" SignTransferEvent" ))
131+
132+ if (! signEventLog ) throw new Error (" SignTransferEvent not found in logs" )
133+ const signEvent: SignTransferEvent = JSON .parse (signEventLog ).SignTransferEvent
134+
135+ // Convert signature to EVM format (adds 27 to recovery_id)
136+ const signature = MPCSignature .fromRaw (signEvent .signature ).toBytes (true )
137+
138+ // Convert the NEAR payload (snake_case OmniAddresses) into the EVM TransferPayload
139+ const stripPrefix = (addr : string ) => (addr .includes (" :" ) ? addr .split (" :" )[1 ] : addr )
140+ let originChain = signEvent .message_payload .transfer_id .origin_chain
141+ if (typeof originChain === " string" ) {
142+ originChain = ChainKind [originChain as keyof typeof ChainKind ]
143+ }
116144
117- // Convert signature for EVM (adds 27 to recovery ID)
118- const signature = MPCSignature .fromSignTransferEvent (signEvent ).toBytes (true )
145+ const payload: TransferPayload = {
146+ destinationNonce: BigInt (signEvent .message_payload .destination_nonce ),
147+ originChain: Number (originChain ),
148+ originNonce: BigInt (signEvent .message_payload .transfer_id .origin_nonce ),
149+ tokenAddress: stripPrefix (signEvent .message_payload .token_address ) as ` 0x${string } ` ,
150+ amount: BigInt (signEvent .message_payload .amount ),
151+ recipient: stripPrefix (signEvent .message_payload .recipient ) as ` 0x${string } ` ,
152+ feeRecipient: signEvent .message_payload .fee_recipient ?? " " ,
153+ }
119154
120- const tx = evm .buildFinalization (signEvent . message_payload , signature )
155+ const tx = evm .buildFinalization (payload , signature )
121156await walletClient .sendTransaction (tx )
122157```
123158
124159<Note >
125- The MPC signature needs format conversion for EVM — use ` MPCSignature.toBytes(true) ` to add 27 to the recovery ID. For Solana, use ` toBytes(false) ` .
160+ The MPC signature needs format conversion for EVM — use ` MPCSignature.fromRaw(raw). toBytes(true) ` to add 27 to the recovery ID. For Solana, pass the ` MPCSignature ` instance directly to the builder .
126161</Note >
127162
128163## From EVM to NEAR
@@ -132,24 +167,27 @@ The MPC signature needs format conversion for EVM — use `MPCSignature.toBytes(
132167Ethereum uses the NEAR light client for verification:
133168
134169``` typescript
135- import { createNearBuilder , toNearKitTransaction } from " @omni-bridge/near"
136- import { getEvmProof , ProofKind } from " @omni-bridge/evm"
170+ import { ChainKind } from " @omni-bridge/core"
171+ import { createNearBuilder , ProofKind , toNearKitTransaction } from " @omni-bridge/near"
172+ import { getEvmProof , getInitTransferTopic } from " @omni-bridge/evm"
137173
138174const nearBuilder = createNearBuilder ({ network: " mainnet" })
139175
140176// Wait for light client to sync (~15-20 min after source tx confirms)
141177
142- // Generate Merkle proof
143- const proof = await getEvmProof (txHash , ChainKind .Eth )
178+ // Generate Merkle proof — needs the InitTransfer event topic and the source network
179+ const proof = await getEvmProof (txHash , getInitTransferTopic (), ChainKind .Eth , " mainnet " )
144180
145- // Serialize for NEAR
146- const proverArgs = nearBuilder .serializeEvmProofArgs ({
147- proof_kind: ProofKind .InitTransfer ,
148- proof ,
181+ // Build and send finalization. `buildFinalization` serializes the proof internally.
182+ const tx = nearBuilder .buildFinalization ({
183+ sourceChain: ChainKind .Eth ,
184+ signerId ,
185+ evmProof: {
186+ proof_kind: ProofKind .InitTransfer ,
187+ proof ,
188+ },
189+ storageDepositActions: [], // add entries for recipient/fee_recipient if needed
149190})
150-
151- // Build and send finalization
152- const tx = nearBuilder .buildFinalization (ChainKind .Eth , proverArgs , signerId )
153191await toNearKitTransaction (near , tx ).send ()
154192```
155193
@@ -163,14 +201,13 @@ import { getWormholeVaa } from "@omni-bridge/core"
163201// Wait for Wormhole guardians to sign (~1 min)
164202const vaa = await getWormholeVaa (txSignature , " Mainnet" )
165203
166- // Serialize for NEAR
167- const proverArgs = nearBuilder .serializeWormholeProofArgs ({
168- proof_kind: ProofKind .InitTransfer ,
204+ // Finalize. `buildFinalization` serializes the VAA internally.
205+ const tx = nearBuilder .buildFinalization ({
206+ sourceChain: ChainKind .Base ,
207+ signerId ,
169208 vaa ,
209+ storageDepositActions: [],
170210})
171-
172- // Finalize
173- const tx = nearBuilder .buildFinalization (ChainKind .Base , proverArgs , signerId )
174211await toNearKitTransaction (near , tx ).send ()
175212```
176213
@@ -183,12 +220,12 @@ import { getWormholeVaa } from "@omni-bridge/core"
183220
184221const vaa = await getWormholeVaa (solanaSignature , " Mainnet" )
185222
186- const proverArgs = nearBuilder .serializeWormholeProofArgs ({
187- proof_kind: ProofKind .InitTransfer ,
223+ const tx = nearBuilder .buildFinalization ({
224+ sourceChain: ChainKind .Sol ,
225+ signerId ,
188226 vaa ,
227+ storageDepositActions: [],
189228})
190-
191- const tx = nearBuilder .buildFinalization (ChainKind .Sol , proverArgs , signerId )
192229await toNearKitTransaction (near , tx ).send ()
193230```
194231
@@ -199,7 +236,7 @@ Each destination has a `buildFinalization` method:
199236| Destination | Method |
200237| -------------| --------|
201238| EVM | ` evmBuilder.buildFinalization(payload, signature) ` |
202- | NEAR | ` nearBuilder.buildFinalization(chain, proverArgs , signerId) ` |
239+ | NEAR | ` nearBuilder.buildFinalization({ sourceChain , signerId, vaa \| evmProof, storageDepositActions } ) ` |
203240| Solana | ` solanaBuilder.buildFinalization(payload, signature, payer) ` |
204241
205242## Working Examples
0 commit comments