@orbi-wallet/sdk 0.0.4 → 0.1.1
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/README.md +38 -238
- package/dist/client.d.ts +41 -94
- package/dist/client.js +143 -215
- package/dist/index.d.ts +1 -2
- package/dist/index.js +1 -3
- package/dist/types.d.ts +16 -25
- package/dist/version.d.ts +2 -0
- package/dist/version.js +6 -0
- package/package.json +15 -12
- package/dist/wallet.d.ts +0 -16
- package/dist/wallet.js +0 -33
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# @orbi-wallet/sdk
|
|
2
2
|
|
|
3
|
-
The official SDK for
|
|
3
|
+
The official SDK for connecting your Stellar dApp to [Orbi Smart Wallet](https://orbiwallet.xyz).
|
|
4
4
|
|
|
5
|
-
Orbi is a passkey-
|
|
5
|
+
Orbi is a passkey-secured **classic Stellar (G) account** wallet. Users sign in and approve transactions with Face ID / Touch ID — no seed phrase, no browser extension.
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
@@ -14,290 +14,90 @@ npm install @orbi-wallet/sdk
|
|
|
14
14
|
|
|
15
15
|
---
|
|
16
16
|
|
|
17
|
-
## Quick
|
|
18
|
-
|
|
19
|
-
### User pays gas (default)
|
|
20
|
-
|
|
21
|
-
```ts
|
|
22
|
-
import { OrbiClient } from '@orbi-wallet/sdk';
|
|
23
|
-
|
|
24
|
-
const orbi = new OrbiClient({
|
|
25
|
-
apiUrl: 'https://api.orbiwallet.xyz',
|
|
26
|
-
});
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
### dApp sponsors gas (gasless)
|
|
17
|
+
## Quick start
|
|
30
18
|
|
|
31
19
|
```ts
|
|
32
20
|
import { OrbiClient } from '@orbi-wallet/sdk';
|
|
33
21
|
|
|
34
|
-
const orbi = new OrbiClient({
|
|
35
|
-
apiUrl: 'https://api.orbiwallet.xyz',
|
|
36
|
-
apiKey: 'YOUR_API_KEY', // get this from developers.orbiwallet.xyz
|
|
37
|
-
});
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
That one line is the only difference. Everything else — connecting, signing, submitting — works exactly the same. Users see the fee crossed out and "Sponsored by [your app]".
|
|
22
|
+
const orbi = new OrbiClient({ network: 'testnet' });
|
|
41
23
|
|
|
42
|
-
|
|
24
|
+
// 1. Connect — opens a popup, resolves once the user approves
|
|
25
|
+
const { walletAddress } = await orbi.connect();
|
|
43
26
|
|
|
44
|
-
|
|
27
|
+
// 2. Build a transaction with @stellar/stellar-sdk and get its XDR
|
|
28
|
+
const xdr = transaction.toXDR();
|
|
45
29
|
|
|
46
|
-
|
|
30
|
+
// 3. Ask the user to review and sign — opens a popup, resolves with the signed XDR
|
|
31
|
+
const { signedXdr } = await orbi.signTransaction({ xdr });
|
|
47
32
|
|
|
48
|
-
|
|
49
|
-
1. orbi.connect() → redirect user to Orbi to connect wallet
|
|
50
|
-
2. orbi.handleCallback() → on return, get wallet address + passkey ID
|
|
51
|
-
3. orbi.sign() → redirect user to approve transaction with passkey
|
|
52
|
-
4. orbi.handleSignCallback() + orbi.bundle() → submit signed tx to relay
|
|
53
|
-
5. orbi.waitForConfirmation(opId) → wait for on-chain confirmation (~5s)
|
|
33
|
+
// 4. Submit signedXdr to Horizon yourself (e.g. server.submitTransaction)
|
|
54
34
|
```
|
|
55
35
|
|
|
56
36
|
---
|
|
57
37
|
|
|
58
|
-
##
|
|
59
|
-
|
|
60
|
-
### Step 1 — Connect wallet
|
|
38
|
+
## How it works
|
|
61
39
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
```ts
|
|
65
|
-
orbi.connect({
|
|
66
|
-
redirectUrl: 'https://yourapp.com/callback',
|
|
67
|
-
});
|
|
68
|
-
// navigates to keys.orbiwallet.xyz, then back to redirectUrl?token=...
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
On your `/callback` page:
|
|
72
|
-
|
|
73
|
-
```ts
|
|
74
|
-
const wallet = await orbi.handleCallback();
|
|
75
|
-
if (wallet) {
|
|
76
|
-
// { walletAddress, passkeyId, email }
|
|
77
|
-
localStorage.setItem('walletAddress', wallet.walletAddress);
|
|
78
|
-
}
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
### Step 2 — Sign and submit a transaction
|
|
82
|
-
|
|
83
|
-
```ts
|
|
84
|
-
// Redirect user to approve
|
|
85
|
-
orbi.sign({
|
|
86
|
-
walletAddress: localStorage.getItem('walletAddress')!,
|
|
87
|
-
contractId: 'YOUR_CONTRACT_ID',
|
|
88
|
-
functionName: 'transfer',
|
|
89
|
-
argsXdr: ['...', '...'], // XDR-encoded args
|
|
90
|
-
redirectUrl: 'https://yourapp.com/sign-callback',
|
|
91
|
-
});
|
|
92
|
-
```
|
|
40
|
+
Orbi uses a **popup + postMessage** handshake — the same integration pattern Coinbase Smart Wallet and most modern wallet SDKs use:
|
|
93
41
|
|
|
94
|
-
|
|
42
|
+
1. `orbi.connect()` / `orbi.signTransaction()` opens `keys.orbiwallet.xyz` in a popup
|
|
43
|
+
2. The user approves with their passkey (signs in, or creates a wallet first if new)
|
|
44
|
+
3. The popup posts the result back to your page and closes itself
|
|
45
|
+
4. The returned promise resolves with the result
|
|
95
46
|
|
|
96
|
-
|
|
97
|
-
const result = orbi.handleSignCallback();
|
|
98
|
-
if (!result) return; // user cancelled or came directly to this page
|
|
99
|
-
|
|
100
|
-
const { opId } = await orbi.bundle({
|
|
101
|
-
walletAddress: result.walletAddress,
|
|
102
|
-
quoteId: result.quoteId,
|
|
103
|
-
signedAuthEntryXdr: result.signedAuthEntryXdr,
|
|
104
|
-
contractId: 'YOUR_CONTRACT_ID',
|
|
105
|
-
functionName: 'transfer',
|
|
106
|
-
argsXdr: result.argsXdr,
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
// Wait for on-chain confirmation via SSE
|
|
110
|
-
const status = await orbi.waitForConfirmation(opId);
|
|
111
|
-
if (status.status === 'confirmed') {
|
|
112
|
-
console.log('tx hash:', status.txHash);
|
|
113
|
-
}
|
|
114
|
-
```
|
|
47
|
+
The connected wallet is cached in `localStorage`, so later `connect()` calls resolve instantly without reopening the popup. Call `disconnect()` to clear it.
|
|
115
48
|
|
|
116
49
|
---
|
|
117
50
|
|
|
118
|
-
## API
|
|
51
|
+
## API
|
|
119
52
|
|
|
120
|
-
### `new OrbiClient(config)`
|
|
53
|
+
### `new OrbiClient(config?)`
|
|
121
54
|
|
|
122
|
-
|
|
|
55
|
+
| Option | Type | Default | Description |
|
|
123
56
|
|---|---|---|---|
|
|
124
|
-
| `
|
|
125
|
-
| `apiKey` | `string` | No | Your developer API key. Enables gas sponsorship. |
|
|
126
|
-
|
|
127
|
-
---
|
|
128
|
-
|
|
129
|
-
### Wallet Connection
|
|
130
|
-
|
|
131
|
-
#### `connect(params)`
|
|
132
|
-
|
|
133
|
-
Redirects the user to Orbi to connect their wallet.
|
|
134
|
-
|
|
135
|
-
```ts
|
|
136
|
-
orbi.connect({ redirectUrl: 'https://yourapp.com/callback' });
|
|
137
|
-
```
|
|
138
|
-
|
|
139
|
-
#### `handleCallback()`
|
|
140
|
-
|
|
141
|
-
Call on your callback page after `connect()` redirects back. Returns wallet data or `null` if no token in URL.
|
|
142
|
-
|
|
143
|
-
```ts
|
|
144
|
-
const wallet = await orbi.handleCallback();
|
|
145
|
-
// { walletAddress: string, passkeyId: string, email: string } | null
|
|
146
|
-
```
|
|
147
|
-
|
|
148
|
-
---
|
|
149
|
-
|
|
150
|
-
### Transaction Signing
|
|
151
|
-
|
|
152
|
-
#### `sign(params)`
|
|
153
|
-
|
|
154
|
-
Redirects the user to Orbi to approve a transaction with their passkey.
|
|
155
|
-
|
|
156
|
-
```ts
|
|
157
|
-
orbi.sign({
|
|
158
|
-
walletAddress: string,
|
|
159
|
-
contractId: string,
|
|
160
|
-
functionName: string,
|
|
161
|
-
argsXdr: string[], // XDR-encoded Soroban args
|
|
162
|
-
redirectUrl: string,
|
|
163
|
-
});
|
|
164
|
-
```
|
|
57
|
+
| `network` | `'testnet' \| 'mainnet'` | `'testnet'` | Stellar network — passed through so Orbi shows the right network badge and validates the transaction against the matching ledger |
|
|
165
58
|
|
|
166
|
-
|
|
59
|
+
### `connect(): Promise<ConnectedWallet>`
|
|
167
60
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
Call on your sign-callback page. Returns the signed data needed to call `bundle()`, or `null` if nothing to process.
|
|
171
|
-
|
|
172
|
-
```ts
|
|
173
|
-
const result = orbi.handleSignCallback();
|
|
174
|
-
// { signedAuthEntryXdr, quoteId, argsXdr, nativeSacId, walletAddress } | null
|
|
175
|
-
```
|
|
176
|
-
|
|
177
|
-
---
|
|
178
|
-
|
|
179
|
-
### Relay
|
|
180
|
-
|
|
181
|
-
#### `bundle(params)`
|
|
182
|
-
|
|
183
|
-
Submit a signed operation to the Orbi relay for on-chain execution.
|
|
184
|
-
|
|
185
|
-
```ts
|
|
186
|
-
const { opId } = await orbi.bundle({
|
|
187
|
-
walletAddress: string,
|
|
188
|
-
quoteId: string,
|
|
189
|
-
signedAuthEntryXdr: string,
|
|
190
|
-
contractId: string,
|
|
191
|
-
functionName: string,
|
|
192
|
-
argsXdr: string[],
|
|
193
|
-
});
|
|
194
|
-
```
|
|
195
|
-
|
|
196
|
-
#### `waitForConfirmation(opId)`
|
|
197
|
-
|
|
198
|
-
Wait for the operation to be confirmed or fail. Uses SSE — resolves in ~5s on Stellar.
|
|
199
|
-
|
|
200
|
-
```ts
|
|
201
|
-
const status = await orbi.waitForConfirmation(opId);
|
|
202
|
-
// { opId, status: 'confirmed' | 'failed', txHash: string | null, error: string | null }
|
|
203
|
-
```
|
|
204
|
-
|
|
205
|
-
#### `getStatus(opId)`
|
|
206
|
-
|
|
207
|
-
One-shot status check (non-blocking alternative to `waitForConfirmation`).
|
|
208
|
-
|
|
209
|
-
```ts
|
|
210
|
-
const status = await orbi.getStatus(opId);
|
|
211
|
-
```
|
|
212
|
-
|
|
213
|
-
---
|
|
214
|
-
|
|
215
|
-
### Token Management
|
|
216
|
-
|
|
217
|
-
#### `watchAsset(params)`
|
|
218
|
-
|
|
219
|
-
Redirect the user to add a Soroban token to their Orbi wallet.
|
|
220
|
-
|
|
221
|
-
```ts
|
|
222
|
-
orbi.watchAsset({
|
|
223
|
-
contractId: 'TOKEN_CONTRACT_ID',
|
|
224
|
-
redirectUrl: 'https://yourapp.com/callback',
|
|
225
|
-
});
|
|
226
|
-
```
|
|
227
|
-
|
|
228
|
-
#### `handleWatchAssetCallback()`
|
|
229
|
-
|
|
230
|
-
Call on your callback page after `watchAsset()` redirects back.
|
|
61
|
+
Connects the user's wallet. Returns a cached session instantly if one exists; otherwise opens the connect popup and resolves once the user approves.
|
|
231
62
|
|
|
232
63
|
```ts
|
|
233
|
-
const
|
|
234
|
-
// { contractId: string, added: boolean } | null
|
|
64
|
+
const { walletAddress, credentialId, passkeyId } = await orbi.connect();
|
|
235
65
|
```
|
|
236
66
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
### Gas Sponsorship (Developer Setup)
|
|
240
|
-
|
|
241
|
-
These methods are for onboarding your dApp to gas sponsorship. You can also do this through the [developer portal](https://developers.orbiwallet.xyz).
|
|
67
|
+
### `signTransaction({ xdr, walletAddress? }): Promise<SignResult>`
|
|
242
68
|
|
|
243
|
-
|
|
69
|
+
Opens the sign popup so the user can review and approve a transaction with their passkey.
|
|
244
70
|
|
|
245
|
-
|
|
71
|
+
- `xdr` — base64-encoded `TransactionEnvelope` XDR for a classic G account (build it with `@stellar/stellar-sdk`)
|
|
72
|
+
- `walletAddress` — optional; defaults to the currently connected address
|
|
246
73
|
|
|
247
74
|
```ts
|
|
248
|
-
const {
|
|
249
|
-
developerName: 'My App',
|
|
250
|
-
email: 'you@example.com',
|
|
251
|
-
});
|
|
75
|
+
const { signedXdr, walletAddress } = await orbi.signTransaction({ xdr });
|
|
252
76
|
```
|
|
253
77
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
Set the Stellar G... address that will fund gas for your users. Requires `apiKey` in constructor.
|
|
257
|
-
|
|
258
|
-
```ts
|
|
259
|
-
await orbi.setDeployer('GABC...XYZ');
|
|
260
|
-
```
|
|
261
|
-
|
|
262
|
-
#### `getDeployerBalance()`
|
|
263
|
-
|
|
264
|
-
Check your gas tank balance. Requires `apiKey` in constructor.
|
|
265
|
-
|
|
266
|
-
```ts
|
|
267
|
-
const { balanceXlm } = await orbi.getDeployerBalance();
|
|
268
|
-
console.log(`${balanceXlm} XLM remaining`);
|
|
269
|
-
```
|
|
270
|
-
|
|
271
|
-
---
|
|
78
|
+
Orbi only signs — it does not submit. Submit `signedXdr` to Horizon yourself.
|
|
272
79
|
|
|
273
|
-
|
|
80
|
+
### `getAddress(): string | null`
|
|
274
81
|
|
|
275
|
-
|
|
82
|
+
Returns the cached wallet address from a previous `connect()`, or `null` if not connected.
|
|
276
83
|
|
|
277
|
-
|
|
278
|
-
2. **Create a Stellar keypair** for your gas tank (a regular G... account)
|
|
279
|
-
3. **Fund it with XLM** — each sponsored transaction deducts the exact network fee
|
|
280
|
-
4. **Set the deployer** in the developer portal (or via `setDeployer()`)
|
|
281
|
-
5. **Add `apiKey`** to your `OrbiClient` constructor
|
|
84
|
+
### `disconnect(): void`
|
|
282
85
|
|
|
283
|
-
|
|
86
|
+
Clears the cached session on your side. Doesn't revoke anything on Orbi — the user can reconnect any time with their passkey.
|
|
284
87
|
|
|
285
88
|
---
|
|
286
89
|
|
|
287
90
|
## Notes
|
|
288
91
|
|
|
289
|
-
-
|
|
290
|
-
-
|
|
291
|
-
-
|
|
292
|
-
- XDR arg encoding: use `@stellar/stellar-sdk` to build and encode Soroban contract args
|
|
92
|
+
- Requires popups to be allowed for your site — `connect()`/`signTransaction()` reject with a clear error if the popup is blocked or the user closes it
|
|
93
|
+
- Works with Orbi G-wallets only (classic Stellar accounts)
|
|
94
|
+
- Results are only ever accepted from `https://keys.orbiwallet.xyz`, verified by both message origin and source window — never trust `postMessage` from elsewhere
|
|
293
95
|
|
|
294
96
|
---
|
|
295
97
|
|
|
296
98
|
## Links
|
|
297
99
|
|
|
298
100
|
- [Orbi Wallet](https://orbiwallet.xyz)
|
|
299
|
-
- [Developer Portal](https://developers.orbiwallet.xyz)
|
|
300
|
-
- [npm](https://npmjs.com/package/@orbi-wallet/sdk)
|
|
301
101
|
- [GitHub](https://github.com/Novablitz404/orbi-smart-wallet)
|
|
302
102
|
|
|
303
103
|
---
|
package/dist/client.d.ts
CHANGED
|
@@ -1,106 +1,53 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @orbi-wallet/sdk — Orbi Smart Wallet SDK
|
|
2
|
+
* @orbi-wallet/sdk — Orbi Smart Wallet SDK (G-wallet)
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Connects a Stellar dApp to Orbi passkey wallets via a popup + postMessage
|
|
5
|
+
* handshake — the same integration pattern Coinbase Smart Wallet uses.
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
* const
|
|
9
|
-
*
|
|
10
|
-
* Quick start (dApp sponsors gas):
|
|
11
|
-
* const orbi = new OrbiClient({
|
|
12
|
-
* apiUrl: 'https://api.orbiwallet.xyz',
|
|
13
|
-
* apiKey: 'YOUR_API_KEY', // <-- enables gasless
|
|
14
|
-
* });
|
|
15
|
-
*
|
|
16
|
-
* Flow:
|
|
17
|
-
* 1. orbi.connect({ redirectUrl }) — redirect user to connect wallet
|
|
18
|
-
* 2. orbi.handleCallback() — on return, exchange token for wallet data
|
|
19
|
-
* 3. orbi.sign({ ..., redirectUrl }) — redirect user to approve transaction
|
|
20
|
-
* 4. orbi.handleSignCallback() → bundle() — on return, submit signed tx
|
|
21
|
-
* 5. orbi.waitForConfirmation(opId) — wait for on-chain confirmation
|
|
7
|
+
* const orbi = new OrbiClient();
|
|
8
|
+
* const { walletAddress } = await orbi.connect();
|
|
9
|
+
* const { signedXdr } = await orbi.signTransaction({ xdr });
|
|
22
10
|
*/
|
|
23
|
-
import type {
|
|
11
|
+
import type { ConnectedWallet, EvmSignResult, OrbiChain, OrbiClientConfig, SignResult } from './types';
|
|
24
12
|
export declare class OrbiClient {
|
|
25
|
-
private
|
|
26
|
-
private
|
|
27
|
-
constructor(config
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
13
|
+
private network;
|
|
14
|
+
private chain;
|
|
15
|
+
constructor(config?: OrbiClientConfig);
|
|
16
|
+
/** Wallet address from a previous `connect()`, restored from local storage. */
|
|
17
|
+
getAddress(): string | null;
|
|
18
|
+
/** Chain of the cached session, if any. */
|
|
19
|
+
getChain(): OrbiChain | null;
|
|
20
|
+
/** Forget the cached session. The next `connect()` reopens the Orbi popup. */
|
|
21
|
+
disconnect(): void;
|
|
22
|
+
private getSession;
|
|
33
23
|
/**
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
* You are responsible for clearing your own local wallet state before calling this.
|
|
24
|
+
* Connect the user's Orbi wallet. Resolves immediately from a cached
|
|
25
|
+
* session if one exists; otherwise opens the Orbi connect popup and
|
|
26
|
+
* resolves once the user approves.
|
|
38
27
|
*/
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
walletAddress: string;
|
|
43
|
-
passkeyId: string;
|
|
44
|
-
email: string;
|
|
45
|
-
} | null>;
|
|
28
|
+
connect(opts?: {
|
|
29
|
+
chain?: OrbiChain;
|
|
30
|
+
}): Promise<ConnectedWallet>;
|
|
46
31
|
/**
|
|
47
|
-
*
|
|
48
|
-
*
|
|
32
|
+
* Ask the user to review and approve a transaction with their passkey.
|
|
33
|
+
*
|
|
34
|
+
* `xdr` is a base64-encoded TransactionEnvelope for a classic G account —
|
|
35
|
+
* build it with `@stellar/stellar-sdk` on your end. Orbi only signs; submit
|
|
36
|
+
* the returned `signedXdr` to Horizon yourself.
|
|
49
37
|
*/
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
argsXdr: string[];
|
|
55
|
-
redirectUrl: string;
|
|
56
|
-
}): void;
|
|
57
|
-
/** Call this on your sign-callback page after orbi.sign() redirects back. */
|
|
58
|
-
handleSignCallback(): {
|
|
59
|
-
signedAuthEntryXdr: string;
|
|
60
|
-
quoteId: string;
|
|
61
|
-
argsXdr: string[];
|
|
62
|
-
nativeSacId: string;
|
|
63
|
-
walletAddress: string;
|
|
64
|
-
} | null;
|
|
65
|
-
/** Redirect the user to add a token to their Orbi wallet. */
|
|
66
|
-
watchAsset(params: {
|
|
67
|
-
contractId: string;
|
|
68
|
-
redirectUrl: string;
|
|
69
|
-
}): void;
|
|
70
|
-
/** Call this on your callback page after orbi.watchAsset() redirects back. */
|
|
71
|
-
handleWatchAssetCallback(): {
|
|
72
|
-
contractId: string;
|
|
73
|
-
added: boolean;
|
|
74
|
-
} | null;
|
|
38
|
+
signTransaction(params: {
|
|
39
|
+
xdr: string;
|
|
40
|
+
walletAddress?: string;
|
|
41
|
+
}): Promise<SignResult>;
|
|
75
42
|
/**
|
|
76
|
-
*
|
|
77
|
-
*
|
|
43
|
+
* Ask the user to review and approve a native-token (BOT) transfer on
|
|
44
|
+
* BotChain. Signing and submission happen inside the Orbi popup — where the
|
|
45
|
+
* passkey lives — so the dApp never touches a key. Returns the tx hash.
|
|
78
46
|
*/
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
argsXdr: string[];
|
|
86
|
-
}): Promise<{
|
|
87
|
-
opId: string;
|
|
88
|
-
}>;
|
|
89
|
-
/** One-shot status check for an operation. */
|
|
90
|
-
getStatus(opId: string): Promise<OpStatus>;
|
|
91
|
-
/** Wait for confirmed or failed via SSE (~5s on Stellar). */
|
|
92
|
-
waitForConfirmation(opId: string): Promise<OpStatus>;
|
|
93
|
-
/** Register a new developer account. Returns a one-time API key — save it. */
|
|
94
|
-
register(params: {
|
|
95
|
-
developerName: string;
|
|
96
|
-
email: string;
|
|
97
|
-
deployerPublicKey?: string;
|
|
98
|
-
}): Promise<{
|
|
99
|
-
apiKey: string;
|
|
100
|
-
message: string;
|
|
101
|
-
}>;
|
|
102
|
-
/** Set or update the deployer (gas tank) address for this API key. */
|
|
103
|
-
setDeployer(deployerPublicKey: string): Promise<void>;
|
|
104
|
-
/** Check the XLM balance of your gas tank. */
|
|
105
|
-
getDeployerBalance(): Promise<DeployerBalance>;
|
|
47
|
+
signEvmTransaction(params: {
|
|
48
|
+
to: string;
|
|
49
|
+
value: string;
|
|
50
|
+
walletAddress?: string;
|
|
51
|
+
}): Promise<EvmSignResult>;
|
|
52
|
+
private openPopup;
|
|
106
53
|
}
|
package/dist/client.js
CHANGED
|
@@ -1,248 +1,176 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
|
-
* @orbi-wallet/sdk — Orbi Smart Wallet SDK
|
|
3
|
+
* @orbi-wallet/sdk — Orbi Smart Wallet SDK (G-wallet)
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
5
|
+
* Connects a Stellar dApp to Orbi passkey wallets via a popup + postMessage
|
|
6
|
+
* handshake — the same integration pattern Coinbase Smart Wallet uses.
|
|
7
7
|
*
|
|
8
|
-
*
|
|
9
|
-
* const
|
|
10
|
-
*
|
|
11
|
-
* Quick start (dApp sponsors gas):
|
|
12
|
-
* const orbi = new OrbiClient({
|
|
13
|
-
* apiUrl: 'https://api.orbiwallet.xyz',
|
|
14
|
-
* apiKey: 'YOUR_API_KEY', // <-- enables gasless
|
|
15
|
-
* });
|
|
16
|
-
*
|
|
17
|
-
* Flow:
|
|
18
|
-
* 1. orbi.connect({ redirectUrl }) — redirect user to connect wallet
|
|
19
|
-
* 2. orbi.handleCallback() — on return, exchange token for wallet data
|
|
20
|
-
* 3. orbi.sign({ ..., redirectUrl }) — redirect user to approve transaction
|
|
21
|
-
* 4. orbi.handleSignCallback() → bundle() — on return, submit signed tx
|
|
22
|
-
* 5. orbi.waitForConfirmation(opId) — wait for on-chain confirmation
|
|
8
|
+
* const orbi = new OrbiClient();
|
|
9
|
+
* const { walletAddress } = await orbi.connect();
|
|
10
|
+
* const { signedXdr } = await orbi.signTransaction({ xdr });
|
|
23
11
|
*/
|
|
24
12
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
13
|
exports.OrbiClient = void 0;
|
|
14
|
+
// Generated from package.json at build time (see scripts/generate-version.js)
|
|
15
|
+
// — package.json stays the single source of truth for name/version.
|
|
16
|
+
const version_1 = require("./version");
|
|
26
17
|
const KEYS_URL = 'https://keys.orbiwallet.xyz';
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
function def(p, n, fn) {
|
|
32
|
-
if (typeof p[n] !== 'function')
|
|
33
|
-
Object.defineProperty(p, n, { value: fn, writable: true, configurable: true });
|
|
34
|
-
}
|
|
35
|
-
function patch(p) {
|
|
36
|
-
if (!p)
|
|
37
|
-
return;
|
|
38
|
-
def(p, 'readBigInt64BE', function (o = 0) { return dv(this).getBigInt64(o, false); });
|
|
39
|
-
def(p, 'readBigUInt64BE', function (o = 0) { return dv(this).getBigUint64(o, false); });
|
|
40
|
-
def(p, 'readBigInt64LE', function (o = 0) { return dv(this).getBigInt64(o, true); });
|
|
41
|
-
def(p, 'readBigUInt64LE', function (o = 0) { return dv(this).getBigUint64(o, true); });
|
|
42
|
-
def(p, 'writeBigInt64BE', function (v, o = 0) { dv(this).setBigInt64(o, v, false); return o + 8; });
|
|
43
|
-
def(p, 'writeBigUInt64BE', function (v, o = 0) { dv(this).setBigUint64(o, v, false); return o + 8; });
|
|
44
|
-
def(p, 'writeBigInt64LE', function (v, o = 0) { dv(this).setBigInt64(o, v, true); return o + 8; });
|
|
45
|
-
def(p, 'writeBigUInt64LE', function (v, o = 0) { dv(this).setBigUint64(o, v, true); return o + 8; });
|
|
46
|
-
}
|
|
47
|
-
patch(Uint8Array.prototype);
|
|
48
|
-
patch(globalThis.Buffer?.prototype);
|
|
49
|
-
}
|
|
18
|
+
const KEYS_ORIGIN = new URL(KEYS_URL).origin;
|
|
19
|
+
const SESSION_KEY = 'orbi_session';
|
|
20
|
+
const POPUP_WIDTH = 420;
|
|
21
|
+
const POPUP_HEIGHT = 640;
|
|
50
22
|
class OrbiClient {
|
|
51
|
-
constructor(config) {
|
|
52
|
-
this.
|
|
53
|
-
this.
|
|
54
|
-
|
|
23
|
+
constructor(config = {}) {
|
|
24
|
+
this.network = config.network ?? 'testnet';
|
|
25
|
+
this.chain = config.chain ?? 'stellar';
|
|
26
|
+
}
|
|
27
|
+
// ── Session ─────────────────────────────────────────────────────────────────
|
|
28
|
+
/** Wallet address from a previous `connect()`, restored from local storage. */
|
|
29
|
+
getAddress() {
|
|
30
|
+
return this.getSession()?.walletAddress ?? null;
|
|
31
|
+
}
|
|
32
|
+
/** Chain of the cached session, if any. */
|
|
33
|
+
getChain() {
|
|
34
|
+
return this.getSession()?.chain ?? null;
|
|
35
|
+
}
|
|
36
|
+
/** Forget the cached session. The next `connect()` reopens the Orbi popup. */
|
|
37
|
+
disconnect() {
|
|
38
|
+
if (typeof window === 'undefined')
|
|
39
|
+
return;
|
|
40
|
+
localStorage.removeItem(SESSION_KEY);
|
|
55
41
|
}
|
|
56
|
-
|
|
57
|
-
|
|
42
|
+
getSession() {
|
|
43
|
+
if (typeof window === 'undefined')
|
|
44
|
+
return null;
|
|
45
|
+
const raw = localStorage.getItem(SESSION_KEY);
|
|
46
|
+
return raw ? JSON.parse(raw) : null;
|
|
58
47
|
}
|
|
59
48
|
// ── Wallet connection ───────────────────────────────────────────────────────
|
|
60
|
-
/** Redirect the user to Orbi to connect their wallet. */
|
|
61
|
-
connect(params) {
|
|
62
|
-
const url = new URL(`${KEYS_URL}/connect`);
|
|
63
|
-
url.searchParams.set('redirect', params.redirectUrl);
|
|
64
|
-
url.searchParams.set('origin', window.location.origin);
|
|
65
|
-
window.location.href = url.toString();
|
|
66
|
-
}
|
|
67
49
|
/**
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
* You are responsible for clearing your own local wallet state before calling this.
|
|
50
|
+
* Connect the user's Orbi wallet. Resolves immediately from a cached
|
|
51
|
+
* session if one exists; otherwise opens the Orbi connect popup and
|
|
52
|
+
* resolves once the user approves.
|
|
72
53
|
*/
|
|
73
|
-
|
|
74
|
-
const
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
const
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
54
|
+
async connect(opts = {}) {
|
|
55
|
+
const chain = opts.chain ?? this.chain;
|
|
56
|
+
// A cached session only satisfies a connect for the *same* chain — the
|
|
57
|
+
// address differs per chain, so a Stellar session can't stand in for a
|
|
58
|
+
// BotChain connect (or vice versa).
|
|
59
|
+
const cached = this.getSession();
|
|
60
|
+
if (cached && cached.chain === chain)
|
|
61
|
+
return cached;
|
|
62
|
+
const wallet = await this.openPopup({
|
|
63
|
+
path: '/connect',
|
|
64
|
+
params: { chain },
|
|
65
|
+
successType: 'orbi_connected',
|
|
66
|
+
mapSuccess: (msg) => ({
|
|
67
|
+
walletAddress: msg.address,
|
|
68
|
+
credentialId: msg.credentialId ?? '',
|
|
69
|
+
passkeyId: msg.passkeyId ?? '',
|
|
70
|
+
chain: (msg.chain ?? chain),
|
|
71
|
+
}),
|
|
72
|
+
});
|
|
73
|
+
localStorage.setItem(SESSION_KEY, JSON.stringify(wallet));
|
|
74
|
+
return wallet;
|
|
88
75
|
}
|
|
89
76
|
// ── Transaction signing ─────────────────────────────────────────────────────
|
|
90
77
|
/**
|
|
91
|
-
*
|
|
92
|
-
*
|
|
78
|
+
* Ask the user to review and approve a transaction with their passkey.
|
|
79
|
+
*
|
|
80
|
+
* `xdr` is a base64-encoded TransactionEnvelope for a classic G account —
|
|
81
|
+
* build it with `@stellar/stellar-sdk` on your end. Orbi only signs; submit
|
|
82
|
+
* the returned `signedXdr` to Horizon yourself.
|
|
93
83
|
*/
|
|
94
|
-
|
|
95
|
-
const
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
const signedXdr = params.get('signedXdr');
|
|
110
|
-
const quoteId = params.get('quoteId');
|
|
111
|
-
const argsXdrRaw = params.get('argsXdr');
|
|
112
|
-
const nativeSacId = params.get('nativeSacId');
|
|
113
|
-
const walletAddress = params.get('walletAddress');
|
|
114
|
-
if (!signedXdr || !quoteId || !argsXdrRaw || !nativeSacId || !walletAddress)
|
|
115
|
-
return null;
|
|
116
|
-
return {
|
|
117
|
-
signedAuthEntryXdr: signedXdr,
|
|
118
|
-
quoteId,
|
|
119
|
-
argsXdr: JSON.parse(argsXdrRaw),
|
|
120
|
-
nativeSacId,
|
|
121
|
-
walletAddress,
|
|
122
|
-
};
|
|
123
|
-
}
|
|
124
|
-
// ── Token management ────────────────────────────────────────────────────────
|
|
125
|
-
/** Redirect the user to add a token to their Orbi wallet. */
|
|
126
|
-
watchAsset(params) {
|
|
127
|
-
const url = new URL(`${KEYS_URL}/watch-asset`);
|
|
128
|
-
url.searchParams.set('contractId', params.contractId);
|
|
129
|
-
url.searchParams.set('redirect', params.redirectUrl);
|
|
130
|
-
url.searchParams.set('origin', window.location.origin);
|
|
131
|
-
window.location.href = url.toString();
|
|
132
|
-
}
|
|
133
|
-
/** Call this on your callback page after orbi.watchAsset() redirects back. */
|
|
134
|
-
handleWatchAssetCallback() {
|
|
135
|
-
const params = new URLSearchParams(window.location.search);
|
|
136
|
-
const contractId = params.get('watchedContractId');
|
|
137
|
-
if (!contractId)
|
|
138
|
-
return null;
|
|
139
|
-
return { contractId, added: params.get('watched') === 'true' };
|
|
84
|
+
signTransaction(params) {
|
|
85
|
+
const walletAddress = params.walletAddress ?? this.getAddress() ?? undefined;
|
|
86
|
+
return this.openPopup({
|
|
87
|
+
path: '/sign',
|
|
88
|
+
params: {
|
|
89
|
+
xdr: params.xdr,
|
|
90
|
+
network: this.network,
|
|
91
|
+
...(walletAddress ? { walletAddress } : {}),
|
|
92
|
+
},
|
|
93
|
+
successType: 'orbi_g_signed',
|
|
94
|
+
mapSuccess: (msg) => ({
|
|
95
|
+
signedXdr: msg.signedXdr,
|
|
96
|
+
walletAddress: msg.walletAddress,
|
|
97
|
+
}),
|
|
98
|
+
});
|
|
140
99
|
}
|
|
141
|
-
// ── Relay API ───────────────────────────────────────────────────────────────
|
|
142
100
|
/**
|
|
143
|
-
*
|
|
144
|
-
*
|
|
101
|
+
* Ask the user to review and approve a native-token (BOT) transfer on
|
|
102
|
+
* BotChain. Signing and submission happen inside the Orbi popup — where the
|
|
103
|
+
* passkey lives — so the dApp never touches a key. Returns the tx hash.
|
|
145
104
|
*/
|
|
146
|
-
|
|
147
|
-
const
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
105
|
+
signEvmTransaction(params) {
|
|
106
|
+
const walletAddress = params.walletAddress ?? this.getAddress() ?? undefined;
|
|
107
|
+
return this.openPopup({
|
|
108
|
+
path: '/sign',
|
|
109
|
+
params: {
|
|
110
|
+
chain: 'botchain',
|
|
111
|
+
to: params.to,
|
|
112
|
+
value: params.value,
|
|
113
|
+
network: this.network,
|
|
114
|
+
...(walletAddress ? { walletAddress } : {}),
|
|
152
115
|
},
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
call: {
|
|
158
|
-
contractId: params.contractId,
|
|
159
|
-
function: params.functionName,
|
|
160
|
-
argsXdr: params.argsXdr,
|
|
161
|
-
},
|
|
116
|
+
successType: 'orbi_evm_sent',
|
|
117
|
+
mapSuccess: (msg) => ({
|
|
118
|
+
txHash: msg.txHash,
|
|
119
|
+
walletAddress: msg.walletAddress,
|
|
162
120
|
}),
|
|
163
121
|
});
|
|
164
|
-
if (!res.ok) {
|
|
165
|
-
const err = await res.json().catch(() => ({}));
|
|
166
|
-
throw new Error(err.error ?? `Bundle failed: ${res.status}`);
|
|
167
|
-
}
|
|
168
|
-
return res.json();
|
|
169
122
|
}
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
123
|
+
// ── Popup + postMessage handshake ───────────────────────────────────────────
|
|
124
|
+
openPopup(req) {
|
|
125
|
+
if (typeof window === 'undefined') {
|
|
126
|
+
return Promise.reject(new Error('Orbi requires a browser environment'));
|
|
127
|
+
}
|
|
128
|
+
const url = new URL(`${KEYS_URL}${req.path}`);
|
|
129
|
+
url.searchParams.set('origin', window.location.origin);
|
|
130
|
+
url.searchParams.set('sdkName', version_1.SDK_NAME);
|
|
131
|
+
url.searchParams.set('sdkVersion', version_1.SDK_VERSION);
|
|
132
|
+
for (const [key, value] of Object.entries(req.params ?? {}))
|
|
133
|
+
url.searchParams.set(key, value);
|
|
134
|
+
const left = window.screenX + Math.max(0, (window.outerWidth - POPUP_WIDTH) / 2);
|
|
135
|
+
const top = window.screenY + Math.max(0, (window.outerHeight - POPUP_HEIGHT) / 2);
|
|
136
|
+
const popup = window.open(url.toString(), 'orbi-wallet', `width=${POPUP_WIDTH},height=${POPUP_HEIGHT},left=${left},top=${top}`);
|
|
137
|
+
if (!popup) {
|
|
138
|
+
return Promise.reject(new Error('Popup blocked — allow popups for this site to use Orbi'));
|
|
139
|
+
}
|
|
179
140
|
return new Promise((resolve, reject) => {
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
141
|
+
let settled = false;
|
|
142
|
+
const settle = (fn) => {
|
|
143
|
+
if (settled)
|
|
144
|
+
return;
|
|
145
|
+
settled = true;
|
|
146
|
+
window.removeEventListener('message', onMessage);
|
|
147
|
+
clearInterval(closedCheck);
|
|
148
|
+
fn();
|
|
149
|
+
};
|
|
150
|
+
const onMessage = (event) => {
|
|
151
|
+
// event.origin is never affected by Cross-Origin-Opener-Policy and
|
|
152
|
+
// can't be spoofed — always required. event.source (the popup window
|
|
153
|
+
// reference) adds extra anti-spoofing when the browser provides it,
|
|
154
|
+
// but COOP isolation can null it out on either side, so we only
|
|
155
|
+
// enforce it when present rather than rejecting legit messages.
|
|
156
|
+
if (event.origin !== KEYS_ORIGIN)
|
|
157
|
+
return;
|
|
158
|
+
if (event.source !== null && event.source !== popup)
|
|
159
|
+
return;
|
|
160
|
+
const data = event.data;
|
|
161
|
+
if (data?.type === req.successType) {
|
|
162
|
+
settle(() => resolve(req.mapSuccess(data)));
|
|
194
163
|
}
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
reject(new Error('Invalid SSE response'));
|
|
164
|
+
else if (data?.type === 'orbi_cancelled') {
|
|
165
|
+
settle(() => reject(new Error('Cancelled in Orbi')));
|
|
198
166
|
}
|
|
199
167
|
};
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
};
|
|
204
|
-
|
|
205
|
-
}
|
|
206
|
-
// ── Gas sponsorship onboarding ──────────────────────────────────────────────
|
|
207
|
-
/** Register a new developer account. Returns a one-time API key — save it. */
|
|
208
|
-
async register(params) {
|
|
209
|
-
const res = await fetch(`${this.apiUrl}/v1/account/register`, {
|
|
210
|
-
method: 'POST',
|
|
211
|
-
headers: { 'Content-Type': 'application/json' },
|
|
212
|
-
body: JSON.stringify(params),
|
|
213
|
-
});
|
|
214
|
-
if (!res.ok) {
|
|
215
|
-
const err = await res.json().catch(() => ({}));
|
|
216
|
-
throw new Error(err.error ?? `Registration failed: ${res.status}`);
|
|
217
|
-
}
|
|
218
|
-
return res.json();
|
|
219
|
-
}
|
|
220
|
-
/** Set or update the deployer (gas tank) address for this API key. */
|
|
221
|
-
async setDeployer(deployerPublicKey) {
|
|
222
|
-
if (!this.apiKey)
|
|
223
|
-
throw new Error('apiKey required — pass it in the OrbiClient constructor');
|
|
224
|
-
const res = await fetch(`${this.apiUrl}/v1/account/deployer`, {
|
|
225
|
-
method: 'PATCH',
|
|
226
|
-
headers: { 'Content-Type': 'application/json', ...this.authHeaders() },
|
|
227
|
-
body: JSON.stringify({ deployerPublicKey }),
|
|
168
|
+
const closedCheck = setInterval(() => {
|
|
169
|
+
if (popup.closed)
|
|
170
|
+
settle(() => reject(new Error('Orbi window closed before completing')));
|
|
171
|
+
}, 500);
|
|
172
|
+
window.addEventListener('message', onMessage);
|
|
228
173
|
});
|
|
229
|
-
if (!res.ok) {
|
|
230
|
-
const err = await res.json().catch(() => ({}));
|
|
231
|
-
throw new Error(err.error ?? `Set deployer failed: ${res.status}`);
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
/** Check the XLM balance of your gas tank. */
|
|
235
|
-
async getDeployerBalance() {
|
|
236
|
-
if (!this.apiKey)
|
|
237
|
-
throw new Error('apiKey required — pass it in the OrbiClient constructor');
|
|
238
|
-
const res = await fetch(`${this.apiUrl}/v1/account/balance`, {
|
|
239
|
-
headers: this.authHeaders(),
|
|
240
|
-
});
|
|
241
|
-
if (!res.ok) {
|
|
242
|
-
const err = await res.json().catch(() => ({}));
|
|
243
|
-
throw new Error(err.error ?? `Balance fetch failed: ${res.status}`);
|
|
244
|
-
}
|
|
245
|
-
return res.json();
|
|
246
174
|
}
|
|
247
175
|
}
|
|
248
176
|
exports.OrbiClient = OrbiClient;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,2 @@
|
|
|
1
1
|
export { OrbiClient } from './client';
|
|
2
|
-
export {
|
|
3
|
-
export type { OrbiClientConfig, QuoteResult, BundleResult, OpStatus, OrbiNetwork, DeployerBalance } from './types';
|
|
2
|
+
export type { ConnectedWallet, EvmSignResult, OrbiChain, OrbiClientConfig, OrbiNetwork, SignResult } from './types';
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.OrbiClient = void 0;
|
|
4
4
|
var client_1 = require("./client");
|
|
5
5
|
Object.defineProperty(exports, "OrbiClient", { enumerable: true, get: function () { return client_1.OrbiClient; } });
|
|
6
|
-
var wallet_1 = require("./wallet");
|
|
7
|
-
Object.defineProperty(exports, "deriveWalletAddress", { enumerable: true, get: function () { return wallet_1.deriveWalletAddress; } });
|
package/dist/types.d.ts
CHANGED
|
@@ -1,32 +1,23 @@
|
|
|
1
1
|
export type OrbiNetwork = 'testnet' | 'mainnet';
|
|
2
|
+
/** Which chain the wallet operates on. One passkey backs every chain. */
|
|
3
|
+
export type OrbiChain = 'stellar' | 'botchain';
|
|
2
4
|
export interface OrbiClientConfig {
|
|
3
|
-
/**
|
|
4
|
-
apiUrl: string;
|
|
5
|
-
/** Optional: your API key if required by the relay */
|
|
6
|
-
apiKey?: string;
|
|
5
|
+
/** Network the dApp is operating on. Defaults to 'testnet'. */
|
|
7
6
|
network?: OrbiNetwork;
|
|
7
|
+
/** Chain to connect on. Defaults to 'stellar'. */
|
|
8
|
+
chain?: OrbiChain;
|
|
8
9
|
}
|
|
9
|
-
export interface
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
currentLedger: number;
|
|
15
|
-
nativeSacId: string;
|
|
16
|
-
feeCollectorAddress: string;
|
|
17
|
-
authEntryXdr: string;
|
|
10
|
+
export interface ConnectedWallet {
|
|
11
|
+
walletAddress: string;
|
|
12
|
+
credentialId: string;
|
|
13
|
+
passkeyId: string;
|
|
14
|
+
chain: OrbiChain;
|
|
18
15
|
}
|
|
19
|
-
export interface
|
|
20
|
-
|
|
16
|
+
export interface SignResult {
|
|
17
|
+
signedXdr: string;
|
|
18
|
+
walletAddress: string;
|
|
21
19
|
}
|
|
22
|
-
export interface
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
txHash: string | null;
|
|
26
|
-
error: string | null;
|
|
27
|
-
}
|
|
28
|
-
export interface DeployerBalance {
|
|
29
|
-
address: string;
|
|
30
|
-
balanceXlm: string;
|
|
31
|
-
balanceStroops: string;
|
|
20
|
+
export interface EvmSignResult {
|
|
21
|
+
txHash: string;
|
|
22
|
+
walletAddress: string;
|
|
32
23
|
}
|
package/dist/version.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SDK_VERSION = exports.SDK_NAME = void 0;
|
|
4
|
+
// Generated by scripts/generate-version.js from package.json — do not edit.
|
|
5
|
+
exports.SDK_NAME = "@orbi-wallet/sdk";
|
|
6
|
+
exports.SDK_VERSION = "0.1.1";
|
package/package.json
CHANGED
|
@@ -1,32 +1,35 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@orbi-wallet/sdk",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Orbi Smart Wallet SDK — connect any dApp to Orbi passkey wallets
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "Orbi Smart Wallet SDK — connect any Stellar or BotChain dApp to Orbi passkey wallets",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
|
-
"files": [
|
|
7
|
+
"files": [
|
|
8
|
+
"dist"
|
|
9
|
+
],
|
|
8
10
|
"license": "MIT",
|
|
9
|
-
"keywords": [
|
|
11
|
+
"keywords": [
|
|
12
|
+
"stellar",
|
|
13
|
+
"wallet",
|
|
14
|
+
"passkey",
|
|
15
|
+
"sdk"
|
|
16
|
+
],
|
|
10
17
|
"homepage": "https://orbiwallet.xyz",
|
|
11
18
|
"repository": {
|
|
12
19
|
"type": "git",
|
|
13
|
-
"url": "https://github.com/Novablitz404/orbi-
|
|
20
|
+
"url": "git+https://github.com/Novablitz404/orbi-wallet-sdk.git"
|
|
14
21
|
},
|
|
15
22
|
"bugs": {
|
|
16
|
-
"url": "https://github.com/Novablitz404/orbi-
|
|
23
|
+
"url": "https://github.com/Novablitz404/orbi-wallet-sdk/issues"
|
|
17
24
|
},
|
|
18
25
|
"scripts": {
|
|
26
|
+
"prebuild": "node scripts/generate-version.js",
|
|
19
27
|
"build": "tsc",
|
|
28
|
+
"predev": "node scripts/generate-version.js",
|
|
20
29
|
"dev": "tsc --watch"
|
|
21
30
|
},
|
|
22
|
-
"dependencies": {
|
|
23
|
-
"@stellar/stellar-sdk": "^15.1.0"
|
|
24
|
-
},
|
|
25
31
|
"devDependencies": {
|
|
26
32
|
"@types/node": "^20.14.2",
|
|
27
33
|
"typescript": "^5.5.2"
|
|
28
|
-
},
|
|
29
|
-
"peerDependencies": {
|
|
30
|
-
"@stellar/stellar-sdk": "^15.1.0"
|
|
31
34
|
}
|
|
32
35
|
}
|
package/dist/wallet.d.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
export type OrbiNetwork = 'testnet' | 'mainnet';
|
|
2
|
-
/**
|
|
3
|
-
* Derive the deterministic wallet C-address for a passkey ID.
|
|
4
|
-
*
|
|
5
|
-
* Matches the relay's deriveWalletAddress — same formula:
|
|
6
|
-
* salt = sha256(passkey_id)
|
|
7
|
-
* address = sha256(networkId + deployer_G_address + salt)
|
|
8
|
-
*
|
|
9
|
-
* Call this immediately after passkey creation to show the user their
|
|
10
|
-
* address — no transaction or network call needed.
|
|
11
|
-
*/
|
|
12
|
-
export declare function deriveWalletAddress(params: {
|
|
13
|
-
passkeyId: Uint8Array;
|
|
14
|
-
deployerPublicKey: string;
|
|
15
|
-
network?: OrbiNetwork;
|
|
16
|
-
}): string;
|
package/dist/wallet.js
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.deriveWalletAddress = deriveWalletAddress;
|
|
4
|
-
const stellar_sdk_1 = require("@stellar/stellar-sdk");
|
|
5
|
-
const PASSPHRASES = {
|
|
6
|
-
testnet: stellar_sdk_1.Networks.TESTNET,
|
|
7
|
-
mainnet: stellar_sdk_1.Networks.PUBLIC,
|
|
8
|
-
};
|
|
9
|
-
/**
|
|
10
|
-
* Derive the deterministic wallet C-address for a passkey ID.
|
|
11
|
-
*
|
|
12
|
-
* Matches the relay's deriveWalletAddress — same formula:
|
|
13
|
-
* salt = sha256(passkey_id)
|
|
14
|
-
* address = sha256(networkId + deployer_G_address + salt)
|
|
15
|
-
*
|
|
16
|
-
* Call this immediately after passkey creation to show the user their
|
|
17
|
-
* address — no transaction or network call needed.
|
|
18
|
-
*/
|
|
19
|
-
function deriveWalletAddress(params) {
|
|
20
|
-
const { passkeyId, deployerPublicKey, network = 'testnet' } = params;
|
|
21
|
-
const networkPassphrase = PASSPHRASES[network];
|
|
22
|
-
const salt = (0, stellar_sdk_1.hash)(Buffer.from(passkeyId));
|
|
23
|
-
const networkId = (0, stellar_sdk_1.hash)(Buffer.from(networkPassphrase));
|
|
24
|
-
const preimage = stellar_sdk_1.xdr.HashIdPreimage.envelopeTypeContractId(new stellar_sdk_1.xdr.HashIdPreimageContractId({
|
|
25
|
-
networkId: Buffer.from(networkId),
|
|
26
|
-
contractIdPreimage: stellar_sdk_1.xdr.ContractIdPreimage.contractIdPreimageFromAddress(new stellar_sdk_1.xdr.ContractIdPreimageFromAddress({
|
|
27
|
-
address: new stellar_sdk_1.Address(deployerPublicKey).toScAddress(),
|
|
28
|
-
salt: Buffer.from(salt),
|
|
29
|
-
})),
|
|
30
|
-
}));
|
|
31
|
-
const contractId = (0, stellar_sdk_1.hash)(preimage.toXDR());
|
|
32
|
-
return stellar_sdk_1.StrKey.encodeContract(contractId);
|
|
33
|
-
}
|