@arbilink/sdk 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +255 -0
- package/dist/ArbiLink.d.ts +112 -0
- package/dist/ArbiLink.d.ts.map +1 -0
- package/dist/ArbiLink.js +257 -0
- package/dist/ArbiLink.js.map +1 -0
- package/dist/abi/MessageHub.json +156 -0
- package/dist/abi/Receiver.json +211 -0
- package/dist/constants.d.ts +13 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +53 -0
- package/dist/constants.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +35 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +53 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +22 -0
- package/dist/types.js.map +1 -0
- package/dist/utils.d.ts +50 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +99 -0
- package/dist/utils.js.map +1 -0
- package/package.json +46 -0
- package/src/ArbiLink.ts +301 -0
- package/src/abi/MessageHub.json +156 -0
- package/src/abi/Receiver.json +211 -0
- package/src/constants.ts +60 -0
- package/src/index.ts +41 -0
- package/src/types.ts +82 -0
- package/src/utils.ts +111 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Martins-O
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
# @arbilink/sdk
|
|
2
|
+
|
|
3
|
+
Cross-chain messaging made simple. Send messages from **Arbitrum** to any supported chain with a single function call.
|
|
4
|
+
|
|
5
|
+
Built on top of the ArbiLink MessageHub — an optimistic cross-chain relay protocol running on Arbitrum Stylus.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @arbilink/sdk ethers
|
|
11
|
+
# or
|
|
12
|
+
yarn add @arbilink/sdk ethers
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Quick Start
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
import { ArbiLink, encodeCall } from '@arbilink/sdk';
|
|
19
|
+
import { ethers } from 'ethers';
|
|
20
|
+
import { parseAbi } from 'viem';
|
|
21
|
+
|
|
22
|
+
// 1. Connect a signer (must be on Arbitrum Sepolia)
|
|
23
|
+
const provider = new ethers.BrowserProvider(window.ethereum);
|
|
24
|
+
const signer = await provider.getSigner();
|
|
25
|
+
|
|
26
|
+
// 2. Initialise
|
|
27
|
+
const arbiLink = new ArbiLink(signer);
|
|
28
|
+
|
|
29
|
+
// 3. Send a cross-chain message
|
|
30
|
+
const messageId = await arbiLink.sendMessage({
|
|
31
|
+
to: 'ethereum', // destination chain name or numeric ID
|
|
32
|
+
target: '0x742d35Cc...', // contract to call on the destination chain
|
|
33
|
+
data: encodeCall({
|
|
34
|
+
abi: parseAbi(['function mint(address to, uint256 amount)']),
|
|
35
|
+
functionName: 'mint',
|
|
36
|
+
args: ['0xRecipient...', 1_000n],
|
|
37
|
+
}),
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
console.log('Message sent! ID:', messageId);
|
|
41
|
+
|
|
42
|
+
// 4. Watch for delivery
|
|
43
|
+
const unwatch = arbiLink.watchMessage(messageId, (msg) => {
|
|
44
|
+
console.log('Status update:', msg.status);
|
|
45
|
+
if (msg.status === 'confirmed') {
|
|
46
|
+
console.log('Message delivered!');
|
|
47
|
+
unwatch();
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## API Reference
|
|
53
|
+
|
|
54
|
+
### `new ArbiLink(signerOrProvider)`
|
|
55
|
+
|
|
56
|
+
| Mode | Arg | Read | Write |
|
|
57
|
+
|------|-----|------|-------|
|
|
58
|
+
| Full | `ethers.Signer` | ✅ | ✅ |
|
|
59
|
+
| Read-only | `ethers.Provider` | ✅ | ❌ |
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
### `sendMessage(params)` → `Promise<bigint>`
|
|
64
|
+
|
|
65
|
+
Send a cross-chain message. Returns the message ID.
|
|
66
|
+
|
|
67
|
+
```typescript
|
|
68
|
+
const messageId = await arbiLink.sendMessage({
|
|
69
|
+
to: 'base', // 'ethereum' | 'base' | 'polygon' | 'optimism' | chainId
|
|
70
|
+
target: '0xTarget...',
|
|
71
|
+
data: '0xcalldata...',
|
|
72
|
+
fee: 1_000_000_000_000_000n, // optional – fetched from hub if omitted
|
|
73
|
+
});
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
### `getMessageStatus(messageId)` → `Promise<Message>`
|
|
79
|
+
|
|
80
|
+
```typescript
|
|
81
|
+
const msg = await arbiLink.getMessageStatus(1n);
|
|
82
|
+
|
|
83
|
+
console.log(msg.status); // 'pending' | 'relayed' | 'confirmed' | 'failed'
|
|
84
|
+
console.log(msg.sender); // address that sent the message
|
|
85
|
+
console.log(msg.destinationChain); // numeric chain ID
|
|
86
|
+
console.log(msg.feePaid); // bigint (wei)
|
|
87
|
+
console.log(msg.relayer); // relayer address (once confirmed)
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
### `calculateFee(chainId)` → `Promise<bigint>`
|
|
93
|
+
|
|
94
|
+
```typescript
|
|
95
|
+
const fee = await arbiLink.calculateFee(11155111);
|
|
96
|
+
console.log(formatEth(fee)); // "0.001 ETH"
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
### `watchMessage(messageId, callback)` → `() => void`
|
|
102
|
+
|
|
103
|
+
Subscribe to `MessageConfirmed` and `MessageChallenged` events.
|
|
104
|
+
Returns an **unsubscribe** function.
|
|
105
|
+
|
|
106
|
+
```typescript
|
|
107
|
+
const unwatch = arbiLink.watchMessage(messageId, (msg) => {
|
|
108
|
+
if (msg.status === 'confirmed' || msg.status === 'failed') {
|
|
109
|
+
unwatch();
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
### `getChainInfo(chainId)` → `Promise<{ enabled, receiverAddress, baseFee } | null>`
|
|
117
|
+
|
|
118
|
+
```typescript
|
|
119
|
+
const info = await arbiLink.getChainInfo(11155111);
|
|
120
|
+
console.log(info?.enabled); // true
|
|
121
|
+
console.log(info?.receiverAddress); // '0x...'
|
|
122
|
+
console.log(info?.baseFee); // bigint
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
### `registerRelayer(stakeOverride?)` / `exitRelayer()`
|
|
128
|
+
|
|
129
|
+
```typescript
|
|
130
|
+
// Register with the hub's minimum stake
|
|
131
|
+
await arbiLink.registerRelayer();
|
|
132
|
+
|
|
133
|
+
// Or override the stake amount
|
|
134
|
+
await arbiLink.registerRelayer(2_000_000_000_000_000_000n); // 2 ETH
|
|
135
|
+
|
|
136
|
+
// Withdraw stake and deregister
|
|
137
|
+
await arbiLink.exitRelayer();
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## Utility Functions
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
import {
|
|
146
|
+
encodeCall,
|
|
147
|
+
formatMessageId,
|
|
148
|
+
formatEth,
|
|
149
|
+
statusLabel,
|
|
150
|
+
estimateDeliveryTime,
|
|
151
|
+
} from '@arbilink/sdk';
|
|
152
|
+
|
|
153
|
+
encodeCall({ abi, functionName, args }); // → '0x...'
|
|
154
|
+
formatMessageId(42n); // → '#000042'
|
|
155
|
+
formatEth(1_000_000_000_000_000n); // → '0.001 ETH'
|
|
156
|
+
statusLabel('confirmed'); // → 'Confirmed'
|
|
157
|
+
estimateDeliveryTime(11155111); // → seconds (int)
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## Supported Chains
|
|
163
|
+
|
|
164
|
+
| Chain | Name | Chain ID | Status |
|
|
165
|
+
|-------|------|----------|--------|
|
|
166
|
+
| Ethereum Sepolia | `'ethereum'` | 11155111 | ✅ Supported |
|
|
167
|
+
| Base Sepolia | `'base'` | 84532 | ✅ Supported |
|
|
168
|
+
| Polygon Amoy | `'polygon'` | 80002 | 🔜 Coming soon |
|
|
169
|
+
| Optimism Sepolia | `'optimism'` | 11155420 | 🔜 Coming soon |
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
## Full Examples
|
|
174
|
+
|
|
175
|
+
### NFT Mint on Ethereum
|
|
176
|
+
|
|
177
|
+
```typescript
|
|
178
|
+
import { ArbiLink, encodeCall } from '@arbilink/sdk';
|
|
179
|
+
import { parseAbi } from 'viem';
|
|
180
|
+
|
|
181
|
+
const arbiLink = new ArbiLink(signer);
|
|
182
|
+
|
|
183
|
+
const data = encodeCall({
|
|
184
|
+
abi: parseAbi(['function mint(address to, uint256 tokenId)']),
|
|
185
|
+
functionName: 'mint',
|
|
186
|
+
args: ['0xRecipient...', 1n],
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
const messageId = await arbiLink.sendMessage({
|
|
190
|
+
to: 'ethereum',
|
|
191
|
+
target: NFT_CONTRACT_ADDRESS,
|
|
192
|
+
data,
|
|
193
|
+
});
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### Token Transfer on Base
|
|
197
|
+
|
|
198
|
+
```typescript
|
|
199
|
+
const data = encodeCall({
|
|
200
|
+
abi: parseAbi(['function transfer(address to, uint256 amount)']),
|
|
201
|
+
functionName: 'transfer',
|
|
202
|
+
args: [recipient, amount],
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
const messageId = await arbiLink.sendMessage({
|
|
206
|
+
to: 'base',
|
|
207
|
+
target: TOKEN_CONTRACT_ADDRESS,
|
|
208
|
+
data,
|
|
209
|
+
});
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### Read-only status polling (no wallet required)
|
|
213
|
+
|
|
214
|
+
```typescript
|
|
215
|
+
import { ArbiLink } from '@arbilink/sdk';
|
|
216
|
+
import { ethers } from 'ethers';
|
|
217
|
+
|
|
218
|
+
const provider = new ethers.JsonRpcProvider('https://sepolia-rollup.arbitrum.io/rpc');
|
|
219
|
+
const arbiLink = new ArbiLink(provider);
|
|
220
|
+
|
|
221
|
+
const msg = await arbiLink.getMessageStatus(42n);
|
|
222
|
+
console.log(msg.status); // 'confirmed'
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
---
|
|
226
|
+
|
|
227
|
+
## How ArbiLink Works
|
|
228
|
+
|
|
229
|
+
1. **User** calls `sendMessage()` on the **MessageHub** (Arbitrum Stylus).
|
|
230
|
+
2. **Relayers** watch for `MessageSent` events and deliver the message on the destination chain via `ArbiLinkReceiver.receiveMessage()`.
|
|
231
|
+
3. The relayer submits an **ECDSA execution proof** and calls `confirm_delivery()` on the hub, opening a **5-minute challenge window**.
|
|
232
|
+
4. Anyone can call `challenge_message()` with a fraud proof during that window. A valid fraud proof **slashes the relayer's stake**.
|
|
233
|
+
5. After the window closes without a challenge, `finalize_message()` marks the message as **confirmed**.
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
## Configuration
|
|
238
|
+
|
|
239
|
+
After running `scripts/deploy.sh`, update `src/constants.ts` with your deployed addresses:
|
|
240
|
+
|
|
241
|
+
```typescript
|
|
242
|
+
// packages/sdk/src/constants.ts
|
|
243
|
+
export const MESSAGE_HUB_ADDRESS = '0xYourMessageHubAddress';
|
|
244
|
+
|
|
245
|
+
export const RECEIVER_ADDRESSES: Record<number, string> = {
|
|
246
|
+
11155111: '0xYourEthReceiver',
|
|
247
|
+
84532: '0xYourBaseReceiver',
|
|
248
|
+
};
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
---
|
|
252
|
+
|
|
253
|
+
## License
|
|
254
|
+
|
|
255
|
+
MIT
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { ethers } from 'ethers';
|
|
2
|
+
import { type Message, type SendMessageParams, type WatchOptions } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* ArbiLink SDK — send cross-chain messages from Arbitrum to any supported chain.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```typescript
|
|
8
|
+
* // With a signer (full read/write access)
|
|
9
|
+
* const arbiLink = new ArbiLink(signer);
|
|
10
|
+
*
|
|
11
|
+
* // With a provider (read-only: getMessageStatus, calculateFee)
|
|
12
|
+
* const arbiLink = new ArbiLink(provider);
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
export declare class ArbiLink {
|
|
16
|
+
private readonly provider;
|
|
17
|
+
private readonly signer;
|
|
18
|
+
private readonly messageHub;
|
|
19
|
+
private readonly iface;
|
|
20
|
+
constructor(signerOrProvider: ethers.Signer | ethers.Provider);
|
|
21
|
+
/**
|
|
22
|
+
* Send a cross-chain message from Arbitrum to any supported chain.
|
|
23
|
+
*
|
|
24
|
+
* @returns The message ID assigned by the hub.
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```typescript
|
|
28
|
+
* const arbiLink = new ArbiLink(signer);
|
|
29
|
+
*
|
|
30
|
+
* const messageId = await arbiLink.sendMessage({
|
|
31
|
+
* to: 'ethereum',
|
|
32
|
+
* target: '0x742d35Cc6634C0532925a3b844BC454e4438f44e',
|
|
33
|
+
* data: encodeCall({
|
|
34
|
+
* abi: myABI,
|
|
35
|
+
* functionName: 'mint',
|
|
36
|
+
* args: [recipient, amount],
|
|
37
|
+
* }),
|
|
38
|
+
* });
|
|
39
|
+
*
|
|
40
|
+
* console.log('Sent:', formatMessageId(messageId)); // → "#000001"
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
sendMessage(params: SendMessageParams): Promise<bigint>;
|
|
44
|
+
/**
|
|
45
|
+
* Query the current status and metadata of a message.
|
|
46
|
+
*
|
|
47
|
+
* Fetches the status code from the hub and enriches it with data from
|
|
48
|
+
* `MessageSent` and `MessageConfirmed` event logs.
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* ```typescript
|
|
52
|
+
* const msg = await arbiLink.getMessageStatus(messageId);
|
|
53
|
+
* console.log(msg.status); // 'pending' | 'confirmed'
|
|
54
|
+
* console.log(msg.destinationChain); // 11155111
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
getMessageStatus(messageId: bigint): Promise<Message>;
|
|
58
|
+
/**
|
|
59
|
+
* Fetch the base fee (in wei) required to send a message to `chainId`.
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* ```typescript
|
|
63
|
+
* const fee = await arbiLink.calculateFee(11155111);
|
|
64
|
+
* console.log(formatEth(fee)); // "0.001 ETH"
|
|
65
|
+
* ```
|
|
66
|
+
*/
|
|
67
|
+
calculateFee(chainId: number): Promise<bigint>;
|
|
68
|
+
/**
|
|
69
|
+
* Subscribe to confirmation events for a given message.
|
|
70
|
+
*
|
|
71
|
+
* The callback fires when a `MessageConfirmed` event is emitted for this
|
|
72
|
+
* message ID. Call the returned function to unsubscribe.
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* ```typescript
|
|
76
|
+
* const unwatch = arbiLink.watchMessage(messageId, (msg) => {
|
|
77
|
+
* console.log('Update:', msg.status);
|
|
78
|
+
* if (msg.status === 'confirmed') unwatch();
|
|
79
|
+
* });
|
|
80
|
+
* ```
|
|
81
|
+
*/
|
|
82
|
+
watchMessage(messageId: bigint, callback: (message: Message) => void, _options?: WatchOptions): () => void;
|
|
83
|
+
/**
|
|
84
|
+
* Check whether `address` is a registered, active relayer.
|
|
85
|
+
*/
|
|
86
|
+
isActiveRelayer(address: string): Promise<boolean>;
|
|
87
|
+
/**
|
|
88
|
+
* Register the signer as a relayer by staking the required ETH.
|
|
89
|
+
* Fetches the minimum stake from the hub automatically.
|
|
90
|
+
*
|
|
91
|
+
* @param stakeOverride - Override the minimum stake amount (wei).
|
|
92
|
+
*/
|
|
93
|
+
registerRelayer(stakeOverride?: bigint): Promise<void>;
|
|
94
|
+
/**
|
|
95
|
+
* Withdraw the signer's relayer stake and deregister.
|
|
96
|
+
*/
|
|
97
|
+
exitRelayer(): Promise<void>;
|
|
98
|
+
/**
|
|
99
|
+
* Total number of messages sent through the hub.
|
|
100
|
+
*/
|
|
101
|
+
messageCount(): Promise<bigint>;
|
|
102
|
+
/**
|
|
103
|
+
* The hub owner address.
|
|
104
|
+
*/
|
|
105
|
+
owner(): Promise<string>;
|
|
106
|
+
/**
|
|
107
|
+
* Minimum stake (wei) required to register as a relayer.
|
|
108
|
+
*/
|
|
109
|
+
minStake(): Promise<bigint>;
|
|
110
|
+
private requireSigner;
|
|
111
|
+
}
|
|
112
|
+
//# sourceMappingURL=ArbiLink.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ArbiLink.d.ts","sourceRoot":"","sources":["../src/ArbiLink.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAGhC,OAAO,EAAiB,KAAK,OAAO,EAAsB,KAAK,iBAAiB,EAAE,KAAK,YAAY,EAAE,MAAM,SAAS,CAAC;AAKrH;;;;;;;;;;;GAWG;AACH,qBAAa,QAAQ;IACnB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAkB;IAC3C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAuB;IAC9C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAkB;IAC7C,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAmB;gBAE7B,gBAAgB,EAAE,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC,QAAQ;IAyB7D;;;;;;;;;;;;;;;;;;;;;OAqBG;IACG,WAAW,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC;IAwC7D;;;;;;;;;;;;OAYG;IACG,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAmD3D;;;;;;;;OAQG;IACG,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAUpD;;;;;;;;;;;;;OAaG;IACH,YAAY,CACV,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,EACpC,QAAQ,GAAE,YAAiB,GAC1B,MAAM,IAAI;IAuBb;;OAEG;IACG,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAIxD;;;;;OAKG;IACG,eAAe,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAS5D;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;IAQlC;;OAEG;IACG,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC;IAIrC;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC;IAI9B;;OAEG;IACG,QAAQ,IAAI,OAAO,CAAC,MAAM,CAAC;IAMjC,OAAO,CAAC,aAAa;CAOtB"}
|
package/dist/ArbiLink.js
ADDED
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.ArbiLink = void 0;
|
|
7
|
+
const ethers_1 = require("ethers");
|
|
8
|
+
const MessageHub_json_1 = __importDefault(require("./abi/MessageHub.json"));
|
|
9
|
+
const constants_1 = require("./constants");
|
|
10
|
+
const types_1 = require("./types");
|
|
11
|
+
const utils_1 = require("./utils");
|
|
12
|
+
// ── ArbiLink SDK ──────────────────────────────────────────────────────────────
|
|
13
|
+
/**
|
|
14
|
+
* ArbiLink SDK — send cross-chain messages from Arbitrum to any supported chain.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```typescript
|
|
18
|
+
* // With a signer (full read/write access)
|
|
19
|
+
* const arbiLink = new ArbiLink(signer);
|
|
20
|
+
*
|
|
21
|
+
* // With a provider (read-only: getMessageStatus, calculateFee)
|
|
22
|
+
* const arbiLink = new ArbiLink(provider);
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
class ArbiLink {
|
|
26
|
+
constructor(signerOrProvider) {
|
|
27
|
+
// Distinguish signer from provider: signers expose `getAddress()`
|
|
28
|
+
const isSigner = typeof signerOrProvider.getAddress === 'function';
|
|
29
|
+
if (isSigner) {
|
|
30
|
+
this.signer = signerOrProvider;
|
|
31
|
+
const p = this.signer.provider;
|
|
32
|
+
if (!p)
|
|
33
|
+
throw new types_1.ArbiLinkError('Signer has no attached provider. Connect your signer to a network first.');
|
|
34
|
+
this.provider = p;
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
this.signer = null;
|
|
38
|
+
this.provider = signerOrProvider;
|
|
39
|
+
}
|
|
40
|
+
this.iface = new ethers_1.ethers.Interface(MessageHub_json_1.default);
|
|
41
|
+
this.messageHub = new ethers_1.ethers.Contract(constants_1.MESSAGE_HUB_ADDRESS, MessageHub_json_1.default, isSigner ? this.signer : this.provider);
|
|
42
|
+
}
|
|
43
|
+
// ── Core: send ─────────────────────────────────────────────────────────────
|
|
44
|
+
/**
|
|
45
|
+
* Send a cross-chain message from Arbitrum to any supported chain.
|
|
46
|
+
*
|
|
47
|
+
* @returns The message ID assigned by the hub.
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* ```typescript
|
|
51
|
+
* const arbiLink = new ArbiLink(signer);
|
|
52
|
+
*
|
|
53
|
+
* const messageId = await arbiLink.sendMessage({
|
|
54
|
+
* to: 'ethereum',
|
|
55
|
+
* target: '0x742d35Cc6634C0532925a3b844BC454e4438f44e',
|
|
56
|
+
* data: encodeCall({
|
|
57
|
+
* abi: myABI,
|
|
58
|
+
* functionName: 'mint',
|
|
59
|
+
* args: [recipient, amount],
|
|
60
|
+
* }),
|
|
61
|
+
* });
|
|
62
|
+
*
|
|
63
|
+
* console.log('Sent:', formatMessageId(messageId)); // → "#000001"
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
async sendMessage(params) {
|
|
67
|
+
this.requireSigner();
|
|
68
|
+
const chainId = (0, utils_1.resolveChainId)(params.to);
|
|
69
|
+
const fee = params.fee ?? await this.calculateFee(chainId);
|
|
70
|
+
let tx;
|
|
71
|
+
try {
|
|
72
|
+
tx = await this.messageHub.sendMessage(chainId, params.target, params.data, { value: fee });
|
|
73
|
+
}
|
|
74
|
+
catch (err) {
|
|
75
|
+
throw types_1.ArbiLinkError.from(err, `Failed to send message to chain ${chainId}`);
|
|
76
|
+
}
|
|
77
|
+
const receipt = await tx.wait();
|
|
78
|
+
if (!receipt)
|
|
79
|
+
throw new types_1.ArbiLinkError('Transaction receipt is null – the tx may have been dropped');
|
|
80
|
+
// Parse MessageSent event to extract the assigned message ID
|
|
81
|
+
for (const log of receipt.logs) {
|
|
82
|
+
try {
|
|
83
|
+
const parsed = this.iface.parseLog({ topics: [...log.topics], data: log.data });
|
|
84
|
+
if (parsed?.name === 'MessageSent') {
|
|
85
|
+
return parsed.args.messageId;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
// Log from a different contract – skip
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
throw new types_1.ArbiLinkError('MessageSent event not found in receipt. The transaction may have succeeded but used an unexpected hub version.');
|
|
93
|
+
}
|
|
94
|
+
// ── Core: status ───────────────────────────────────────────────────────────
|
|
95
|
+
/**
|
|
96
|
+
* Query the current status and metadata of a message.
|
|
97
|
+
*
|
|
98
|
+
* Fetches the status code from the hub and enriches it with data from
|
|
99
|
+
* `MessageSent` and `MessageConfirmed` event logs.
|
|
100
|
+
*
|
|
101
|
+
* @example
|
|
102
|
+
* ```typescript
|
|
103
|
+
* const msg = await arbiLink.getMessageStatus(messageId);
|
|
104
|
+
* console.log(msg.status); // 'pending' | 'confirmed'
|
|
105
|
+
* console.log(msg.destinationChain); // 11155111
|
|
106
|
+
* ```
|
|
107
|
+
*/
|
|
108
|
+
async getMessageStatus(messageId) {
|
|
109
|
+
try {
|
|
110
|
+
const statusCode = await this.messageHub.getMessageStatus(messageId);
|
|
111
|
+
const status = (0, utils_1.parseStatusCode)(Number(statusCode));
|
|
112
|
+
// Enrich from MessageSent event
|
|
113
|
+
const sentFilter = this.messageHub.filters['MessageSent'](messageId);
|
|
114
|
+
const sentLogs = await this.messageHub.queryFilter(sentFilter);
|
|
115
|
+
let sender;
|
|
116
|
+
let destinationChain;
|
|
117
|
+
let target;
|
|
118
|
+
let data;
|
|
119
|
+
let feePaid;
|
|
120
|
+
if (sentLogs.length > 0) {
|
|
121
|
+
const e = sentLogs[0];
|
|
122
|
+
sender = e.args.sender;
|
|
123
|
+
destinationChain = Number(e.args.destinationChain);
|
|
124
|
+
target = e.args.target;
|
|
125
|
+
data = e.args.data;
|
|
126
|
+
feePaid = e.args.fee;
|
|
127
|
+
}
|
|
128
|
+
// Enrich from MessageConfirmed event (present only when confirmed)
|
|
129
|
+
let relayer;
|
|
130
|
+
if (status === 'confirmed' || status === 'relayed') {
|
|
131
|
+
const confirmedFilter = this.messageHub.filters['MessageConfirmed'](messageId);
|
|
132
|
+
const confirmedLogs = await this.messageHub.queryFilter(confirmedFilter);
|
|
133
|
+
if (confirmedLogs.length > 0) {
|
|
134
|
+
relayer = confirmedLogs[0].args.relayer;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return {
|
|
138
|
+
id: messageId,
|
|
139
|
+
status,
|
|
140
|
+
sender,
|
|
141
|
+
destinationChain,
|
|
142
|
+
target,
|
|
143
|
+
data,
|
|
144
|
+
feePaid,
|
|
145
|
+
relayer,
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
catch (err) {
|
|
149
|
+
throw types_1.ArbiLinkError.from(err, `Failed to fetch status for message #${messageId}`);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
// ── Core: fee ──────────────────────────────────────────────────────────────
|
|
153
|
+
/**
|
|
154
|
+
* Fetch the base fee (in wei) required to send a message to `chainId`.
|
|
155
|
+
*
|
|
156
|
+
* @example
|
|
157
|
+
* ```typescript
|
|
158
|
+
* const fee = await arbiLink.calculateFee(11155111);
|
|
159
|
+
* console.log(formatEth(fee)); // "0.001 ETH"
|
|
160
|
+
* ```
|
|
161
|
+
*/
|
|
162
|
+
async calculateFee(chainId) {
|
|
163
|
+
try {
|
|
164
|
+
return await this.messageHub.calculateFee(chainId);
|
|
165
|
+
}
|
|
166
|
+
catch (err) {
|
|
167
|
+
throw types_1.ArbiLinkError.from(err, `Failed to fetch fee for chain ${chainId}`);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
// ── Core: watch ────────────────────────────────────────────────────────────
|
|
171
|
+
/**
|
|
172
|
+
* Subscribe to confirmation events for a given message.
|
|
173
|
+
*
|
|
174
|
+
* The callback fires when a `MessageConfirmed` event is emitted for this
|
|
175
|
+
* message ID. Call the returned function to unsubscribe.
|
|
176
|
+
*
|
|
177
|
+
* @example
|
|
178
|
+
* ```typescript
|
|
179
|
+
* const unwatch = arbiLink.watchMessage(messageId, (msg) => {
|
|
180
|
+
* console.log('Update:', msg.status);
|
|
181
|
+
* if (msg.status === 'confirmed') unwatch();
|
|
182
|
+
* });
|
|
183
|
+
* ```
|
|
184
|
+
*/
|
|
185
|
+
watchMessage(messageId, callback, _options = {}) {
|
|
186
|
+
const confirmedFilter = this.messageHub.filters['MessageConfirmed'](messageId);
|
|
187
|
+
const listener = async () => {
|
|
188
|
+
try {
|
|
189
|
+
const msg = await this.getMessageStatus(messageId);
|
|
190
|
+
callback(msg);
|
|
191
|
+
}
|
|
192
|
+
catch (err) {
|
|
193
|
+
// Surface the error through the callback rather than throwing from
|
|
194
|
+
// an event listener (which would be silently swallowed by ethers)
|
|
195
|
+
console.error('[ArbiLink] watchMessage error:', err);
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
this.messageHub.on(confirmedFilter, listener);
|
|
199
|
+
return () => {
|
|
200
|
+
this.messageHub.off(confirmedFilter, listener);
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
// ── Relayer helpers ────────────────────────────────────────────────────────
|
|
204
|
+
/**
|
|
205
|
+
* Check whether `address` is a registered, active relayer.
|
|
206
|
+
*/
|
|
207
|
+
async isActiveRelayer(address) {
|
|
208
|
+
return await this.messageHub.isActiveRelayer(address);
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Register the signer as a relayer by staking the required ETH.
|
|
212
|
+
* Fetches the minimum stake from the hub automatically.
|
|
213
|
+
*
|
|
214
|
+
* @param stakeOverride - Override the minimum stake amount (wei).
|
|
215
|
+
*/
|
|
216
|
+
async registerRelayer(stakeOverride) {
|
|
217
|
+
this.requireSigner();
|
|
218
|
+
const stake = stakeOverride ?? await this.messageHub.minStake();
|
|
219
|
+
const tx = await this.messageHub.registerRelayer({ value: stake });
|
|
220
|
+
await tx.wait();
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Withdraw the signer's relayer stake and deregister.
|
|
224
|
+
*/
|
|
225
|
+
async exitRelayer() {
|
|
226
|
+
this.requireSigner();
|
|
227
|
+
const tx = await this.messageHub.exitRelayer();
|
|
228
|
+
await tx.wait();
|
|
229
|
+
}
|
|
230
|
+
// ── Hub info ───────────────────────────────────────────────────────────────
|
|
231
|
+
/**
|
|
232
|
+
* Total number of messages sent through the hub.
|
|
233
|
+
*/
|
|
234
|
+
async messageCount() {
|
|
235
|
+
return await this.messageHub.messageCount();
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* The hub owner address.
|
|
239
|
+
*/
|
|
240
|
+
async owner() {
|
|
241
|
+
return await this.messageHub.owner();
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Minimum stake (wei) required to register as a relayer.
|
|
245
|
+
*/
|
|
246
|
+
async minStake() {
|
|
247
|
+
return await this.messageHub.minStake();
|
|
248
|
+
}
|
|
249
|
+
// ── Private helpers ────────────────────────────────────────────────────────
|
|
250
|
+
requireSigner() {
|
|
251
|
+
if (!this.signer) {
|
|
252
|
+
throw new types_1.ArbiLinkError('This operation requires a Signer. Initialize ArbiLink with an ethers.Signer instead of a Provider.');
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
exports.ArbiLink = ArbiLink;
|
|
257
|
+
//# sourceMappingURL=ArbiLink.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ArbiLink.js","sourceRoot":"","sources":["../src/ArbiLink.ts"],"names":[],"mappings":"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"}
|