@veridex/sdk 1.0.0-beta.17 → 1.0.0-beta.20
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 +416 -117
- package/dist/auth/prepareAuth.d.mts +25 -0
- package/dist/auth/prepareAuth.d.ts +25 -0
- package/dist/auth/prepareAuth.js +1553 -0
- package/dist/auth/prepareAuth.js.map +1 -0
- package/dist/auth/prepareAuth.mjs +1530 -0
- package/dist/auth/prepareAuth.mjs.map +1 -0
- package/dist/chains/aptos/index.d.mts +1 -1
- package/dist/chains/aptos/index.d.ts +1 -1
- package/dist/chains/evm/index.d.mts +2 -2
- package/dist/chains/evm/index.d.ts +2 -2
- package/dist/chains/solana/index.d.mts +1 -1
- package/dist/chains/solana/index.d.ts +1 -1
- package/dist/chains/stacks/index.d.mts +1 -1
- package/dist/chains/stacks/index.d.ts +1 -1
- package/dist/chains/starknet/index.d.mts +1 -1
- package/dist/chains/starknet/index.d.ts +1 -1
- package/dist/chains/sui/index.d.mts +1 -1
- package/dist/chains/sui/index.d.ts +1 -1
- package/dist/{index-CYOyIE3b.d.mts → index-Dy29mvBf.d.mts} +1 -1
- package/dist/{index-BXcR_ypI.d.ts → index-eXXqodd0.d.ts} +1 -1
- package/dist/index.d.mts +103 -25
- package/dist/index.d.ts +103 -25
- package/dist/index.js +198 -25
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +185 -17
- package/dist/index.mjs.map +1 -1
- package/dist/queries/index.js +36 -1
- package/dist/queries/index.js.map +1 -1
- package/dist/queries/index.mjs +36 -1
- package/dist/queries/index.mjs.map +1 -1
- package/dist/{types-DE2ICQik.d.mts → types-DakHNZIP.d.mts} +2 -0
- package/dist/{types-DE2ICQik.d.ts → types-DakHNZIP.d.ts} +2 -0
- package/dist/types.d.mts +2 -0
- package/dist/types.d.ts +2 -0
- package/dist/types.js.map +1 -1
- package/package.json +6 -1
package/README.md
CHANGED
|
@@ -3,213 +3,512 @@
|
|
|
3
3
|
[](https://www.npmjs.com/package/@veridex/sdk)
|
|
4
4
|
[](https://opensource.org/licenses/MIT)
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
**Passkey-based cross-chain identity and authentication.** One passkey. Every chain.
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
## Features
|
|
11
|
-
|
|
12
|
-
- **Passkey Authentication** - WebAuthn P-256 signature verification (no seed phrases)
|
|
13
|
-
- **Cross-Chain Support** - EVM, Solana, Aptos, Sui, Starknet
|
|
14
|
-
- **Deterministic Vaults** - Same address across all EVM chains
|
|
15
|
-
- **Gasless Transactions** - Relayer-sponsored execution
|
|
16
|
-
- **Session Keys** - Temporary delegated access for smooth UX
|
|
17
|
-
- **Wormhole Integration** - Guardian-attested cross-chain messaging
|
|
18
|
-
|
|
19
|
-
## Installation
|
|
8
|
+
Register a WebAuthn passkey once, get a deterministic vault address on every supported chain. No seed phrases, no private keys, no browser extensions.
|
|
20
9
|
|
|
21
10
|
```bash
|
|
22
11
|
npm install @veridex/sdk ethers
|
|
23
|
-
# or
|
|
24
|
-
yarn add @veridex/sdk ethers
|
|
25
|
-
# or
|
|
26
|
-
bun add @veridex/sdk ethers
|
|
27
12
|
```
|
|
28
13
|
|
|
29
|
-
## Quick Start
|
|
30
|
-
|
|
31
14
|
```typescript
|
|
32
15
|
import { createSDK } from '@veridex/sdk';
|
|
33
16
|
|
|
34
|
-
// Initialize
|
|
17
|
+
// Initialize — returns synchronously, defaults to testnet
|
|
35
18
|
const sdk = createSDK('base');
|
|
36
19
|
|
|
37
|
-
// Register a passkey
|
|
20
|
+
// Register a passkey (biometric prompt)
|
|
38
21
|
const credential = await sdk.passkey.register('user@example.com', 'My Wallet');
|
|
39
22
|
|
|
40
|
-
//
|
|
41
|
-
const
|
|
42
|
-
console.log('Your vault:',
|
|
23
|
+
// Deterministic vault address derived from your passkey
|
|
24
|
+
const vault = sdk.getVaultAddress();
|
|
25
|
+
console.log('Your vault:', vault);
|
|
43
26
|
|
|
44
|
-
//
|
|
45
|
-
await sdk.
|
|
27
|
+
// Prepare and execute a transfer (requires a signer to pay gas)
|
|
28
|
+
const prepared = await sdk.prepareTransfer({
|
|
29
|
+
targetChain: 10004, // Base Sepolia Wormhole chain ID
|
|
46
30
|
token: '0x036CbD53842c5426634e7929541eC2318f3dCF7e', // USDC
|
|
47
31
|
recipient: '0x742d35Cc6634C0532925a3b844Bc9e7595f5A234',
|
|
48
|
-
amount: 1000000n,
|
|
32
|
+
amount: 1000000n, // 1 USDC (6 decimals)
|
|
49
33
|
});
|
|
34
|
+
const result = await sdk.executeTransfer(prepared, signer);
|
|
35
|
+
console.log('Tx hash:', result.transactionHash);
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Architecture
|
|
39
|
+
|
|
50
40
|
```
|
|
41
|
+
┌─────────────────────┐
|
|
42
|
+
│ WebAuthn Passkey │
|
|
43
|
+
│ (P-256 / secp256r1)│
|
|
44
|
+
└──────────┬──────────┘
|
|
45
|
+
│
|
|
46
|
+
┌──────────▼──────────┐
|
|
47
|
+
│ Veridex Hub │
|
|
48
|
+
│ (Base / EVM) │
|
|
49
|
+
│ Identity + Vaults │
|
|
50
|
+
└──────────┬──────────┘
|
|
51
|
+
│ Wormhole / Custom Bridge
|
|
52
|
+
┌────────┬───────────┼───────────┬────────┬────────┐
|
|
53
|
+
▼ ▼ ▼ ▼ ▼ ▼
|
|
54
|
+
Solana Aptos Sui Starknet Stacks EVM Spokes
|
|
55
|
+
(Ed25519) (Ed25519) (secp256k1) (Stark) (secp256r1) (Opt/Arb/Poly)
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
**Hub-and-Spoke model**: Identity lives on the Hub (Base). Actions are dispatched to spoke chains via Wormhole guardian-attested messages or custom bridge attestations.
|
|
59
|
+
|
|
60
|
+
## Supported Chains
|
|
61
|
+
|
|
62
|
+
| Chain | Type | Wormhole ID | Signature | Networks |
|
|
63
|
+
|-------|------|-------------|-----------|----------|
|
|
64
|
+
| **Base** | Hub (EVM) | 30 | secp256r1 (passkey) + secp256k1 (session) | Sepolia + Mainnet |
|
|
65
|
+
| **Ethereum** | Spoke (EVM) | 2 | secp256r1 + secp256k1 | Sepolia + Mainnet |
|
|
66
|
+
| **Optimism** | Spoke (EVM) | 24 | secp256r1 + secp256k1 | Sepolia + Mainnet |
|
|
67
|
+
| **Arbitrum** | Spoke (EVM) | 23 | secp256r1 + secp256k1 | Sepolia + Mainnet |
|
|
68
|
+
| **Polygon** | Spoke (EVM) | 5 | secp256r1 + secp256k1 | Amoy + Mainnet |
|
|
69
|
+
| **Monad** | Spoke (EVM) | 10048 | secp256r1 (EIP-7951) + secp256k1 | Testnet + Mainnet |
|
|
70
|
+
| **Solana** | Spoke | 1 | Ed25519 | Devnet + Mainnet |
|
|
71
|
+
| **Aptos** | Spoke | 22 | Ed25519 | Testnet + Mainnet |
|
|
72
|
+
| **Sui** | Spoke | 21 | secp256k1 | Testnet + Mainnet |
|
|
73
|
+
| **Starknet** | Spoke | 50001 | Stark ECDSA | Sepolia + Mainnet |
|
|
74
|
+
| **Stacks** | Spoke | 60 | secp256r1 (native!) + secp256k1 | Testnet + Mainnet |
|
|
75
|
+
|
|
76
|
+
## Key Features
|
|
51
77
|
|
|
52
|
-
|
|
78
|
+
### Passkey Registration & Authentication
|
|
53
79
|
|
|
54
80
|
```typescript
|
|
55
|
-
|
|
56
|
-
const testnetSdk = createSDK('base');
|
|
81
|
+
import { createSDK } from '@veridex/sdk';
|
|
57
82
|
|
|
58
|
-
|
|
59
|
-
const mainnetSdk = createSDK('base', { network: 'mainnet' });
|
|
83
|
+
const sdk = createSDK('base');
|
|
60
84
|
|
|
61
|
-
//
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
|
|
85
|
+
// Register — triggers biometric prompt, returns credential
|
|
86
|
+
const credential = await sdk.passkey.register('user@example.com', 'My Wallet');
|
|
87
|
+
console.log('Key hash:', credential.keyHash);
|
|
88
|
+
console.log('Credential ID:', credential.credentialId);
|
|
89
|
+
|
|
90
|
+
// Check for existing passkeys
|
|
91
|
+
const stored = sdk.passkey.getAllStoredCredentials();
|
|
92
|
+
if (stored.length > 0) {
|
|
93
|
+
// Authenticate with a discoverable credential (shows passkey picker)
|
|
94
|
+
const { credential, signature } = await sdk.passkey.authenticate();
|
|
95
|
+
console.log('Authenticated as:', credential.keyHash);
|
|
96
|
+
} else {
|
|
97
|
+
// Or set a known credential directly
|
|
98
|
+
sdk.passkey.setCredential({
|
|
99
|
+
credentialId: 'abc123',
|
|
100
|
+
publicKeyX: BigInt('0x...'),
|
|
101
|
+
publicKeyY: BigInt('0x...'),
|
|
102
|
+
keyHash: '0x...',
|
|
103
|
+
});
|
|
104
|
+
}
|
|
65
105
|
```
|
|
66
106
|
|
|
67
|
-
|
|
107
|
+
- **RIP-7212** native P-256 verification on EVM (~3,450 gas)
|
|
108
|
+
- **FCL fallback** for chains without precompile
|
|
109
|
+
- **Stacks** has native `secp256r1-verify` in Clarity — no workarounds needed
|
|
110
|
+
- **Monad** has EIP-7951 P-256 precompile at `0x0100` (6,900 gas)
|
|
111
|
+
|
|
112
|
+
### Deterministic Vaults
|
|
113
|
+
|
|
114
|
+
```typescript
|
|
115
|
+
// Same address on Base, Optimism, Arbitrum, Ethereum, Polygon
|
|
116
|
+
const vault = sdk.getVaultAddress();
|
|
117
|
+
|
|
118
|
+
// Get vault address for a specific chain
|
|
119
|
+
const opVault = sdk.getVaultAddressForChain(24); // Optimism
|
|
120
|
+
|
|
121
|
+
// Check if vault exists on-chain
|
|
122
|
+
const info = await sdk.getVaultInfo();
|
|
123
|
+
console.log('Deployed:', info?.exists);
|
|
124
|
+
|
|
125
|
+
// Create vault (user pays gas)
|
|
126
|
+
const result = await sdk.createVault(signer);
|
|
127
|
+
console.log('Vault created:', result.address);
|
|
128
|
+
|
|
129
|
+
// Or create with sponsored gas (Veridex pays)
|
|
130
|
+
const sponsored = await sdk.createVaultSponsored();
|
|
131
|
+
```
|
|
68
132
|
|
|
69
|
-
|
|
70
|
-
|-------|------|--------|
|
|
71
|
-
| Base | Hub (EVM) | Testnet + Mainnet |
|
|
72
|
-
| Optimism | Spoke (EVM) | Testnet + Mainnet |
|
|
73
|
-
| Arbitrum | Spoke (EVM) | Testnet + Mainnet |
|
|
74
|
-
| Ethereum | Spoke (EVM) | Testnet + Mainnet |
|
|
75
|
-
| Polygon | Spoke (EVM) | Testnet + Mainnet |
|
|
76
|
-
| Solana | Spoke | Devnet + Mainnet |
|
|
77
|
-
| Aptos | Spoke | Testnet + Mainnet |
|
|
78
|
-
| Sui | Spoke | Testnet + Mainnet |
|
|
79
|
-
| Starknet | Spoke | Sepolia + Mainnet |
|
|
133
|
+
### Transfers
|
|
80
134
|
|
|
81
|
-
|
|
135
|
+
```typescript
|
|
136
|
+
import { createSDK } from '@veridex/sdk';
|
|
137
|
+
import { ethers } from 'ethers';
|
|
138
|
+
|
|
139
|
+
const sdk = createSDK('base', { network: 'testnet' });
|
|
140
|
+
|
|
141
|
+
// After registering or setting a credential...
|
|
142
|
+
await sdk.passkey.register('user@example.com', 'My Wallet');
|
|
143
|
+
|
|
144
|
+
// 1. Prepare transfer (shows gas estimate before signing)
|
|
145
|
+
const prepared = await sdk.prepareTransfer({
|
|
146
|
+
targetChain: 10004, // Base Sepolia
|
|
147
|
+
token: '0x036CbD53842c5426634e7929541eC2318f3dCF7e', // USDC
|
|
148
|
+
recipient: '0x742d35Cc6634C0532925a3b844Bc9e7595f5A234',
|
|
149
|
+
amount: 1000000n, // 1 USDC
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
// 2. Show human-readable summary
|
|
153
|
+
const summary = await sdk.getTransactionSummary(prepared);
|
|
154
|
+
console.log(summary.title); // "Transfer"
|
|
155
|
+
console.log(summary.description); // "Send 1.0 USDC to 0x742d...5A234"
|
|
156
|
+
console.log('Gas cost:', prepared.formattedCost);
|
|
157
|
+
|
|
158
|
+
// 3. Execute (signs with passkey, then dispatches)
|
|
159
|
+
const provider = new ethers.JsonRpcProvider('https://sepolia.base.org');
|
|
160
|
+
const signer = new ethers.Wallet(PRIVATE_KEY, provider);
|
|
161
|
+
const result = await sdk.executeTransfer(prepared, signer);
|
|
162
|
+
console.log('Tx hash:', result.transactionHash);
|
|
163
|
+
|
|
164
|
+
// 4. Wait for confirmation
|
|
165
|
+
const state = await sdk.waitForTransaction(result.transactionHash);
|
|
166
|
+
console.log('Confirmed in block:', state.blockNumber);
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### Gasless Transfers (via Relayer)
|
|
82
170
|
|
|
83
171
|
```typescript
|
|
84
172
|
const sdk = createSDK('base', {
|
|
173
|
+
network: 'testnet',
|
|
85
174
|
relayerUrl: 'https://relayer.veridex.network',
|
|
86
175
|
relayerApiKey: 'your-api-key',
|
|
87
176
|
});
|
|
88
177
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
178
|
+
await sdk.passkey.register('user@example.com', 'My Wallet');
|
|
179
|
+
|
|
180
|
+
// Relayer sponsors gas — user pays nothing
|
|
181
|
+
const result = await sdk.transferViaRelayer({
|
|
182
|
+
targetChain: 10004,
|
|
183
|
+
token: '0x036CbD53842c5426634e7929541eC2318f3dCF7e',
|
|
184
|
+
recipient: '0x742d35Cc6634C0532925a3b844Bc9e7595f5A234',
|
|
93
185
|
amount: 1000000n,
|
|
94
186
|
});
|
|
187
|
+
console.log('Tx hash:', result.transactionHash);
|
|
95
188
|
```
|
|
96
189
|
|
|
97
|
-
|
|
190
|
+
### Session Keys
|
|
98
191
|
|
|
99
|
-
|
|
192
|
+
Session keys are managed via the `SessionManager` class, separate from the main SDK:
|
|
100
193
|
|
|
101
194
|
```typescript
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
195
|
+
import { createSDK, SessionManager } from '@veridex/sdk';
|
|
196
|
+
|
|
197
|
+
const sdk = createSDK('base');
|
|
198
|
+
await sdk.passkey.register('user@example.com', 'My Wallet');
|
|
199
|
+
|
|
200
|
+
// SessionManager wraps the SDK for session operations
|
|
201
|
+
const sessionManager = new SessionManager({ sdk });
|
|
202
|
+
|
|
203
|
+
// Create a session (one passkey auth)
|
|
204
|
+
const session = await sessionManager.createSession({
|
|
205
|
+
duration: 3600, // 1 hour
|
|
206
|
+
maxValue: BigInt(1e18), // Max 1 token per tx
|
|
207
|
+
allowedChains: [10004], // Base Sepolia only
|
|
106
208
|
});
|
|
107
209
|
|
|
108
|
-
// Execute
|
|
109
|
-
await
|
|
110
|
-
|
|
210
|
+
// Execute transactions with session key (no biometric prompts)
|
|
211
|
+
await sessionManager.executeWithSession({
|
|
212
|
+
targetChain: 10004,
|
|
213
|
+
token: '0x036CbD53842c5426634e7929541eC2318f3dCF7e',
|
|
214
|
+
recipient: '0x...',
|
|
215
|
+
amount: 1000000n,
|
|
216
|
+
}, session);
|
|
111
217
|
|
|
112
|
-
// Revoke
|
|
113
|
-
await
|
|
218
|
+
// Revoke anytime
|
|
219
|
+
await sessionManager.revokeSession(session);
|
|
114
220
|
```
|
|
115
221
|
|
|
116
|
-
|
|
222
|
+
### Session Key Cryptography (Low-Level)
|
|
117
223
|
|
|
118
224
|
```typescript
|
|
119
|
-
import {
|
|
225
|
+
import {
|
|
226
|
+
generateSecp256k1KeyPair,
|
|
227
|
+
computeSessionKeyHash,
|
|
228
|
+
deriveEncryptionKey,
|
|
229
|
+
encrypt,
|
|
230
|
+
decrypt,
|
|
231
|
+
} from '@veridex/sdk';
|
|
120
232
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
233
|
+
// Generate a session key pair
|
|
234
|
+
const keyPair = generateSecp256k1KeyPair();
|
|
235
|
+
console.log('Public key:', keyPair.publicKey);
|
|
236
|
+
|
|
237
|
+
// Compute on-chain key hash
|
|
238
|
+
const keyHash = computeSessionKeyHash(keyPair.publicKey);
|
|
239
|
+
|
|
240
|
+
// Encrypt private key (only passkey owner can decrypt)
|
|
241
|
+
const encryptionKey = await deriveEncryptionKey(credential.credentialId);
|
|
242
|
+
const encrypted = await encrypt(keyPair.privateKey, encryptionKey);
|
|
243
|
+
const decrypted = await decrypt(encrypted, encryptionKey);
|
|
127
244
|
```
|
|
128
245
|
|
|
129
|
-
|
|
246
|
+
### Cross-Chain Bridging
|
|
130
247
|
|
|
131
|
-
|
|
248
|
+
```typescript
|
|
249
|
+
const sdk = createSDK('base', { network: 'testnet' });
|
|
250
|
+
await sdk.passkey.register('user@example.com', 'My Wallet');
|
|
251
|
+
|
|
252
|
+
// Prepare bridge with fee estimation
|
|
253
|
+
const prepared = await sdk.prepareBridge({
|
|
254
|
+
sourceChain: 10004, // Base Sepolia
|
|
255
|
+
destinationChain: 10005, // Optimism Sepolia
|
|
256
|
+
token: '0x036CbD53842c5426634e7929541eC2318f3dCF7e',
|
|
257
|
+
amount: 1000000n,
|
|
258
|
+
});
|
|
259
|
+
console.log('Bridge fees:', prepared.fees.formattedTotal);
|
|
132
260
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
261
|
+
// Execute with progress tracking
|
|
262
|
+
const result = await sdk.executeBridge(prepared, signer, (progress) => {
|
|
263
|
+
console.log(`Step ${progress.step}/${progress.totalSteps}: ${progress.message}`);
|
|
264
|
+
});
|
|
265
|
+
console.log('Source tx:', result.transactionHash);
|
|
266
|
+
console.log('VAA ready:', !!result.vaa);
|
|
267
|
+
|
|
268
|
+
// Or bridge gaslessly via relayer
|
|
269
|
+
const gaslessResult = await sdk.bridgeViaRelayer({
|
|
270
|
+
sourceChain: 10004,
|
|
271
|
+
destinationChain: 10005,
|
|
272
|
+
token: '0x036CbD53842c5426634e7929541eC2318f3dCF7e',
|
|
273
|
+
amount: 1000000n,
|
|
274
|
+
});
|
|
275
|
+
```
|
|
140
276
|
|
|
141
|
-
###
|
|
277
|
+
### Balances
|
|
142
278
|
|
|
143
279
|
```typescript
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
280
|
+
const sdk = createSDK('base', { network: 'testnet' });
|
|
281
|
+
await sdk.passkey.register('user@example.com', 'My Wallet');
|
|
282
|
+
|
|
283
|
+
// Native token balance
|
|
284
|
+
const native = await sdk.getVaultNativeBalance();
|
|
285
|
+
console.log(`${native.token.symbol}: ${native.formatted}`);
|
|
286
|
+
|
|
287
|
+
// All token balances on current chain
|
|
288
|
+
const portfolio = await sdk.getVaultBalances();
|
|
289
|
+
for (const entry of portfolio.tokens) {
|
|
290
|
+
console.log(`${entry.token.symbol}: ${entry.formatted}`);
|
|
291
|
+
}
|
|
292
|
+
console.log('Total USD:', portfolio.totalUsdValue);
|
|
293
|
+
|
|
294
|
+
// Multi-chain balances
|
|
295
|
+
const multiChain = await sdk.getMultiChainBalances([10004, 10005, 10003]);
|
|
296
|
+
for (const chain of multiChain) {
|
|
297
|
+
console.log(`${chain.chainName}: ${chain.tokens.length} tokens`);
|
|
298
|
+
}
|
|
149
299
|
```
|
|
150
300
|
|
|
151
|
-
###
|
|
301
|
+
### Spending Limits
|
|
152
302
|
|
|
153
303
|
```typescript
|
|
154
|
-
import {
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
304
|
+
import { ethers } from 'ethers';
|
|
305
|
+
|
|
306
|
+
// Check current on-chain spending limits
|
|
307
|
+
const limits = await sdk.getSpendingLimits();
|
|
308
|
+
console.log('Daily remaining:', limits.dailyRemaining);
|
|
309
|
+
|
|
310
|
+
// Check if a specific amount is allowed
|
|
311
|
+
const check = await sdk.checkSpendingLimit(ethers.parseEther('1.0'));
|
|
312
|
+
if (!check.allowed) {
|
|
313
|
+
console.log('Blocked:', check.message);
|
|
314
|
+
console.log('Suggestions:', check.suggestions);
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
// Get formatted limits for UI display
|
|
318
|
+
const formatted = await sdk.getFormattedSpendingLimits();
|
|
319
|
+
console.log(`${formatted.dailyUsedPercentage}% of daily limit used`);
|
|
320
|
+
console.log(`Resets in: ${formatted.timeUntilReset}`);
|
|
321
|
+
|
|
322
|
+
// Update daily limit (requires passkey signature)
|
|
323
|
+
const prepared = await sdk.prepareSetDailyLimit(ethers.parseEther('5.0'));
|
|
324
|
+
await sdk.executeTransfer(prepared, signer);
|
|
160
325
|
```
|
|
161
326
|
|
|
162
|
-
|
|
327
|
+
## Chain Clients
|
|
328
|
+
|
|
329
|
+
Each chain has a dedicated client implementing the `ChainClient` interface:
|
|
163
330
|
|
|
164
331
|
```typescript
|
|
165
|
-
import {
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
} from '@veridex/sdk';
|
|
332
|
+
import { EVMClient } from '@veridex/sdk';
|
|
333
|
+
import { SolanaClient } from '@veridex/sdk';
|
|
334
|
+
import { AptosClient } from '@veridex/sdk';
|
|
335
|
+
import { SuiClient } from '@veridex/sdk';
|
|
336
|
+
import { StarknetClient } from '@veridex/sdk';
|
|
337
|
+
import { StacksClient } from '@veridex/sdk';
|
|
338
|
+
|
|
339
|
+
// Or use subpath imports
|
|
340
|
+
import { EVMClient } from '@veridex/sdk/chains/evm';
|
|
341
|
+
import { StacksClient } from '@veridex/sdk/chains/stacks';
|
|
170
342
|
```
|
|
171
343
|
|
|
172
|
-
|
|
344
|
+
All clients support:
|
|
345
|
+
- `buildTransferPayload()` — Build token transfer payloads
|
|
346
|
+
- `buildExecutePayload()` — Build arbitrary execution payloads
|
|
347
|
+
- `buildBridgePayload()` — Build cross-chain bridge payloads
|
|
348
|
+
- `dispatch()` — Submit signed actions with a signer
|
|
349
|
+
- `computeVaultAddress()` — Derive deterministic vault address
|
|
350
|
+
- `vaultExists()` — Check if vault is deployed
|
|
351
|
+
- `createVault()` — Deploy a vault
|
|
352
|
+
- `getNonce()` — Get replay-protection nonce
|
|
353
|
+
- `getMessageFee()` — Get Wormhole message fee
|
|
173
354
|
|
|
174
|
-
|
|
175
|
-
- **RIP-7212 Support** - Native P-256 verification (~3,450 gas)
|
|
176
|
-
- **FCL Fallback** - Software verification when precompile unavailable
|
|
177
|
-
- **Wormhole VAA** - 13/19 guardian quorum for cross-chain messages
|
|
178
|
-
- **Replay Protection** - Nonce-based action deduplication
|
|
355
|
+
### Stacks-Specific
|
|
179
356
|
|
|
180
|
-
|
|
357
|
+
Stacks has unique capabilities leveraged by the SDK:
|
|
358
|
+
|
|
359
|
+
```typescript
|
|
360
|
+
import {
|
|
361
|
+
StacksClient,
|
|
362
|
+
stacksCompressPublicKey,
|
|
363
|
+
stacksRsToCompactSignature,
|
|
364
|
+
stacksDerToCompactSignature,
|
|
365
|
+
stacksComputeKeyHash,
|
|
366
|
+
buildStxWithdrawalPostConditions,
|
|
367
|
+
isValidStacksPrincipal,
|
|
368
|
+
getStacksExplorerTxUrl,
|
|
369
|
+
} from '@veridex/sdk';
|
|
181
370
|
|
|
182
|
-
|
|
371
|
+
// Native secp256r1 verification (no ZK proofs needed)
|
|
372
|
+
// Native sponsored transactions (gasless built-in)
|
|
373
|
+
// Post-conditions for protocol-level spending safety
|
|
374
|
+
```
|
|
183
375
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
376
|
+
## Factory Functions
|
|
377
|
+
|
|
378
|
+
```typescript
|
|
379
|
+
import {
|
|
380
|
+
createSDK, // Main factory — createSDK('base', { network: 'testnet' })
|
|
381
|
+
createHubSDK, // Shortcut for Base hub — createHubSDK()
|
|
382
|
+
createTestnetSDK, // Force testnet — createTestnetSDK('optimism')
|
|
383
|
+
createMainnetSDK, // Force mainnet — createMainnetSDK('base')
|
|
384
|
+
createSessionSDK, // Session-enabled — createSessionSDK('base')
|
|
385
|
+
} from '@veridex/sdk';
|
|
386
|
+
|
|
387
|
+
// Check supported chains
|
|
388
|
+
import { getSupportedChains, getChainConfig, isChainSupported } from '@veridex/sdk';
|
|
190
389
|
|
|
191
|
-
|
|
390
|
+
const chains = getSupportedChains('testnet');
|
|
391
|
+
console.log('Supported:', chains); // ['base', 'ethereum', 'optimism', ...]
|
|
192
392
|
|
|
193
|
-
|
|
393
|
+
const config = getChainConfig('base', 'testnet');
|
|
394
|
+
console.log('RPC:', config.rpcUrl);
|
|
395
|
+
console.log('Chain ID:', config.chainId);
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
## Types
|
|
194
399
|
|
|
195
400
|
```typescript
|
|
196
401
|
import type {
|
|
197
402
|
ChainName,
|
|
403
|
+
ChainClient,
|
|
404
|
+
ChainConfig,
|
|
198
405
|
NetworkType,
|
|
199
406
|
SimpleSDKConfig,
|
|
200
407
|
TransferParams,
|
|
408
|
+
ExecuteParams,
|
|
201
409
|
BridgeParams,
|
|
202
410
|
SessionKey,
|
|
411
|
+
SessionConfig,
|
|
412
|
+
WebAuthnSignature,
|
|
413
|
+
PasskeyCredential,
|
|
414
|
+
DispatchResult,
|
|
415
|
+
VaultCreationResult,
|
|
416
|
+
PreparedTransfer,
|
|
417
|
+
TransferResult,
|
|
418
|
+
PreparedBridge,
|
|
419
|
+
BridgeResult,
|
|
420
|
+
PortfolioBalance,
|
|
421
|
+
TokenBalance,
|
|
422
|
+
SpendingLimits,
|
|
423
|
+
LimitCheckResult,
|
|
424
|
+
IdentityState,
|
|
425
|
+
UnifiedIdentity,
|
|
203
426
|
} from '@veridex/sdk';
|
|
204
427
|
```
|
|
205
428
|
|
|
429
|
+
## Security
|
|
430
|
+
|
|
431
|
+
- **Passkeys only** — No EOA, no seed phrases, no browser extensions
|
|
432
|
+
- **RIP-7212** — Native P-256 verification (~3,450 gas on EVM)
|
|
433
|
+
- **FCL fallback** — Software verification when precompile unavailable
|
|
434
|
+
- **Wormhole VAA** — 13/19 guardian quorum for cross-chain messages
|
|
435
|
+
- **Custom bridge** — Multi-relayer threshold attestations for Starknet
|
|
436
|
+
- **Replay protection** — Nonce-based action deduplication on all chains
|
|
437
|
+
- **Post-conditions** — Protocol-level spending caps on Stacks
|
|
438
|
+
|
|
439
|
+
## Frontend Requirement
|
|
440
|
+
|
|
441
|
+
> **Important:** This SDK requires a **browser frontend** for passkey operations. WebAuthn (passkeys) can only be created and used in a secure browser context — `sdk.passkey.register()` and `sdk.passkey.authenticate()` trigger native OS biometric prompts (FaceID, TouchID, Windows Hello) that cannot run in Node.js or server-side environments.
|
|
442
|
+
|
|
443
|
+
**You need a frontend to:**
|
|
444
|
+
- **Register passkeys** — `sdk.passkey.register()` must be called from a user-initiated browser event (e.g., button click)
|
|
445
|
+
- **Authenticate** — `sdk.passkey.authenticate()` shows the platform passkey picker in the browser
|
|
446
|
+
- **Store credentials** — Passkey credentials are stored in the browser's platform authenticator (iCloud Keychain, Google Password Manager, etc.)
|
|
447
|
+
|
|
448
|
+
**What can run server-side:**
|
|
449
|
+
- Verifying transactions on-chain
|
|
450
|
+
- Querying balances (`sdk.getVaultBalances()`)
|
|
451
|
+
- Relayer API calls
|
|
452
|
+
- Session key operations (after initial passkey-based creation on the frontend)
|
|
453
|
+
|
|
454
|
+
**Minimal frontend example (React):**
|
|
455
|
+
|
|
456
|
+
```tsx
|
|
457
|
+
'use client';
|
|
458
|
+
import { createSDK } from '@veridex/sdk';
|
|
459
|
+
|
|
460
|
+
const sdk = createSDK('base', { network: 'testnet' });
|
|
461
|
+
|
|
462
|
+
export function PasskeyWallet() {
|
|
463
|
+
const handleCreate = async () => {
|
|
464
|
+
// Must be triggered by user interaction (button click)
|
|
465
|
+
const credential = await sdk.passkey.register('user@example.com', 'My Wallet');
|
|
466
|
+
console.log('Vault:', sdk.getVaultAddress());
|
|
467
|
+
};
|
|
468
|
+
|
|
469
|
+
const handleLogin = async () => {
|
|
470
|
+
const { credential } = await sdk.passkey.authenticate();
|
|
471
|
+
console.log('Authenticated:', credential.keyHash);
|
|
472
|
+
};
|
|
473
|
+
|
|
474
|
+
return (
|
|
475
|
+
<div>
|
|
476
|
+
<button onClick={handleCreate}>Create Wallet</button>
|
|
477
|
+
<button onClick={handleLogin}>Login</button>
|
|
478
|
+
</div>
|
|
479
|
+
);
|
|
480
|
+
}
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
For a complete frontend example, see the [test-app](https://github.com/Veridex-Protocol/demo/tree/main/test-app) or the [React integration guide](https://docs.veridex.network/integrations/react).
|
|
484
|
+
|
|
485
|
+
## Browser Support
|
|
486
|
+
|
|
487
|
+
WebAuthn requires HTTPS and a compatible browser:
|
|
488
|
+
|
|
489
|
+
| Browser | Minimum Version |
|
|
490
|
+
|---------|-----------------|
|
|
491
|
+
| Chrome | 67+ |
|
|
492
|
+
| Firefox | 60+ |
|
|
493
|
+
| Safari | 14+ |
|
|
494
|
+
| Edge | 79+ |
|
|
495
|
+
|
|
496
|
+
## Related Packages
|
|
497
|
+
|
|
498
|
+
| Package | Description |
|
|
499
|
+
|---------|-------------|
|
|
500
|
+
| [`@veridex/agentic-payments`](https://www.npmjs.com/package/@veridex/agentic-payments) | Agent payment SDK — x402, UCP, ACP, AP2, ERC-8004 identity |
|
|
501
|
+
| `@veridex/relayer` | Transaction relayer for gasless execution |
|
|
502
|
+
| `@veridex/contracts` | Smart contracts (EVM, Solana, Aptos, Sui, Starknet, Stacks) |
|
|
503
|
+
|
|
206
504
|
## License
|
|
207
505
|
|
|
208
506
|
MIT
|
|
209
507
|
|
|
210
508
|
## Links
|
|
211
509
|
|
|
212
|
-
- [Documentation](https://docs.veridex.
|
|
510
|
+
- [Documentation](https://docs.veridex.network)
|
|
213
511
|
- [GitHub](https://github.com/Veridex-Protocol/sdk)
|
|
512
|
+
- [npm](https://www.npmjs.com/package/@veridex/sdk)
|
|
214
513
|
- [Discord](https://discord.gg/veridex)
|
|
215
514
|
- [Twitter](https://twitter.com/VeridexProtocol)
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { P as PasskeyCredential, T as TransferParams, E as ExecuteParams, B as BridgeParams } from '../types-DakHNZIP.mjs';
|
|
2
|
+
|
|
3
|
+
type AuthenticateAndPrepareParams = {
|
|
4
|
+
credential: PasskeyCredential;
|
|
5
|
+
action?: TransferParams | ExecuteParams | BridgeParams;
|
|
6
|
+
/** Pre-encoded Hub action payload (hex string). If provided, `action` is ignored. */
|
|
7
|
+
actionPayload?: string;
|
|
8
|
+
targetChain: number;
|
|
9
|
+
};
|
|
10
|
+
type AuthenticateAndPrepareResult = {
|
|
11
|
+
serializedTx: Uint8Array;
|
|
12
|
+
queryProof: Uint8Array<ArrayBufferLike>;
|
|
13
|
+
estimatedLatency: number;
|
|
14
|
+
fallbackAvailable: boolean;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Client-first authentication preparation:
|
|
18
|
+
* - user signs locally (FaceID/TouchID)
|
|
19
|
+
* - client queries Wormhole Query Proxy for Guardian-attested nonce/state
|
|
20
|
+
* - client returns a ready-to-submit relayer payload (JSON bytes)
|
|
21
|
+
* - falls back to RPC nonce if Queries fails
|
|
22
|
+
*/
|
|
23
|
+
declare function authenticateAndPrepare(userParams: AuthenticateAndPrepareParams, apiKey: string): Promise<AuthenticateAndPrepareResult>;
|
|
24
|
+
|
|
25
|
+
export { type AuthenticateAndPrepareParams, type AuthenticateAndPrepareResult, authenticateAndPrepare };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { P as PasskeyCredential, T as TransferParams, E as ExecuteParams, B as BridgeParams } from '../types-DakHNZIP.js';
|
|
2
|
+
|
|
3
|
+
type AuthenticateAndPrepareParams = {
|
|
4
|
+
credential: PasskeyCredential;
|
|
5
|
+
action?: TransferParams | ExecuteParams | BridgeParams;
|
|
6
|
+
/** Pre-encoded Hub action payload (hex string). If provided, `action` is ignored. */
|
|
7
|
+
actionPayload?: string;
|
|
8
|
+
targetChain: number;
|
|
9
|
+
};
|
|
10
|
+
type AuthenticateAndPrepareResult = {
|
|
11
|
+
serializedTx: Uint8Array;
|
|
12
|
+
queryProof: Uint8Array<ArrayBufferLike>;
|
|
13
|
+
estimatedLatency: number;
|
|
14
|
+
fallbackAvailable: boolean;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Client-first authentication preparation:
|
|
18
|
+
* - user signs locally (FaceID/TouchID)
|
|
19
|
+
* - client queries Wormhole Query Proxy for Guardian-attested nonce/state
|
|
20
|
+
* - client returns a ready-to-submit relayer payload (JSON bytes)
|
|
21
|
+
* - falls back to RPC nonce if Queries fails
|
|
22
|
+
*/
|
|
23
|
+
declare function authenticateAndPrepare(userParams: AuthenticateAndPrepareParams, apiKey: string): Promise<AuthenticateAndPrepareResult>;
|
|
24
|
+
|
|
25
|
+
export { type AuthenticateAndPrepareParams, type AuthenticateAndPrepareResult, authenticateAndPrepare };
|