@edge-protocol/sdk 0.4.6 → 0.4.7

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.
Files changed (2) hide show
  1. package/DOCS.md +777 -0
  2. package/package.json +1 -1
package/DOCS.md ADDED
@@ -0,0 +1,777 @@
1
+ # @edge-protocol/sdk — Full Developer Reference
2
+
3
+ > Programmable trust infrastructure for autonomous AI agents on Sui.
4
+ > Give agents your rules, not your keys.
5
+
6
+ ```bash
7
+ pnpm add @edge-protocol/sdk
8
+ ```
9
+
10
+ ---
11
+
12
+ ## Table of Contents
13
+
14
+ - [Core Concepts](#core-concepts)
15
+ - [Installation](#installation)
16
+ - [EdgePass API](#edgepass-api)
17
+ - [Templates](#templates)
18
+ - [PolicyEngine](#policyengine)
19
+ - [Types](#types)
20
+ - [Constants](#constants)
21
+ - [Integration Examples](#integration-examples)
22
+ - [Error Handling](#error-handling)
23
+ - [Architecture](#architecture)
24
+ - [Move Contract](#move-contract)
25
+
26
+ ---
27
+
28
+ ## Core Concepts
29
+
30
+ ### The Problem
31
+
32
+ Every developer building an autonomous agent faces the same unsolved problem:
33
+
34
+ ```
35
+ Option A: Give the agent full wallet access → catastrophic risk
36
+ Option B: Human approves every transaction → defeats the purpose
37
+ Option C: Build custom policy logic → 6-8 weeks of work
38
+ ```
39
+
40
+ **EdgePass is Option D** — a programmable trust boundary enforced on-chain.
41
+
42
+ ### EdgePass
43
+
44
+ An EdgePass is a Sui Move object that encodes a complete trust policy. It lives in the user's wallet — not in a contract. An agent executes against it without ever taking ownership.
45
+
46
+ ```
47
+ budget: $300 · auto-approve: <$50 · escalate: >$100 · merchants: [...] · expiry: 48h
48
+ ```
49
+
50
+ ### Transaction Outcomes
51
+
52
+ Every `sdk.execute()` returns one of three outcomes:
53
+
54
+ ```
55
+ ✅ approved — executed on-chain, digest available
56
+ ⚠️ escalated — exceeds threshold, needs user approval
57
+ 🚫 blocked — policy rejected, reason provided
58
+ ```
59
+
60
+ ### MIST
61
+
62
+ All amounts are in MIST — Sui's base unit.
63
+
64
+ ```typescript
65
+ 1 SUI = 1_000_000_000 MIST
66
+
67
+ import { MIST_PER_SUI } from '@edge-protocol/sdk';
68
+
69
+ const budget = 300n * MIST_PER_SUI; // 300 SUI
70
+ const amount = 18_500_000_000n; // 18.5 SUI
71
+ ```
72
+
73
+ ---
74
+
75
+ ## Installation
76
+
77
+ ```bash
78
+ npm install @edge-protocol/sdk
79
+ # or
80
+ pnpm add @edge-protocol/sdk
81
+ # or
82
+ yarn add @edge-protocol/sdk
83
+ ```
84
+
85
+ ### Requirements
86
+
87
+ - Node.js 18+
88
+ - TypeScript 5.0+ (recommended)
89
+ - A Sui network (testnet or mainnet)
90
+ - An Enoki API key for gas sponsorship
91
+
92
+ ---
93
+
94
+ ## EdgePass API
95
+
96
+ ### `new EdgePass(config)`
97
+
98
+ Initialize the SDK client.
99
+
100
+ ```typescript
101
+ import { EdgePass } from '@edge-protocol/sdk';
102
+
103
+ const sdk = new EdgePass({
104
+ network: 'mainnet', // 'mainnet' | 'testnet' | 'devnet'
105
+ enokiApiKey: 'YOUR_KEY',
106
+ });
107
+ ```
108
+
109
+ ---
110
+
111
+ ### `sdk.create(config, signer)` → `Promise<EdgePassObject>`
112
+
113
+ Mint a new EdgePass as a Move object on Sui.
114
+
115
+ ```typescript
116
+ import { EdgePass, MIST_PER_SUI } from '@edge-protocol/sdk';
117
+
118
+ const pass = await sdk.create({
119
+ budget: 300n * MIST_PER_SUI, // total spend limit
120
+ autoThreshold: 50n * MIST_PER_SUI, // auto-approve below this
121
+ escalateThreshold: 100n * MIST_PER_SUI, // escalate above this
122
+ maxPerTransaction: 200n * MIST_PER_SUI, // optional hard cap per tx
123
+ approvedMerchants: ['Shuttle Express', 'Hydra Bar'],
124
+ expiryMs: 48 * 60 * 60 * 1000, // 48 hours
125
+ owner: userAddress,
126
+ }, signer);
127
+
128
+ console.log(pass.id); // Sui object ID — verifiable on Suiscan
129
+ console.log(pass.expiresAt); // Unix timestamp
130
+ ```
131
+
132
+ **Parameters:**
133
+
134
+ | Field | Type | Required | Description |
135
+ |-------|------|----------|-------------|
136
+ | `budget` | `bigint` | ✅ | Total spend limit in MIST |
137
+ | `autoThreshold` | `bigint` | ✅ | Auto-approve below this amount |
138
+ | `escalateThreshold` | `bigint` | ✅ | Escalate above this amount |
139
+ | `maxPerTransaction` | `bigint` | ❌ | Hard cap per single transaction |
140
+ | `approvedMerchants` | `string[]` | ✅ | Allowlist of merchant identifiers |
141
+ | `expiryMs` | `number` | ✅ | Duration until expiry in milliseconds |
142
+ | `owner` | `string` | ✅ | Sui address of the pass owner |
143
+
144
+ **Constraint:** `autoThreshold < escalateThreshold < budget`
145
+
146
+ ---
147
+
148
+ ### `EdgePass.fromTemplate(template, overrides)` → `EdgePassConfig`
149
+
150
+ Create a config from a pre-built template. Override any field.
151
+
152
+ ```typescript
153
+ // Use a template as-is
154
+ const config = EdgePass.fromTemplate('festival', { owner: userAddress });
155
+
156
+ // Override specific fields
157
+ const config = EdgePass.fromTemplate('defi', {
158
+ budget: 25_000n * MIST_PER_SUI,
159
+ approvedMerchants: ['DeepBook', 'Cetus', 'Turbos'],
160
+ owner: userAddress,
161
+ });
162
+
163
+ const pass = await sdk.create(config, signer);
164
+ ```
165
+
166
+ ---
167
+
168
+ ### `sdk.execute(pass, request, signer)` → `Promise<TransactionOutcome>`
169
+
170
+ Execute a transaction against an EdgePass. Policy is validated before touching the chain — blocked and escalated transactions never reach Sui.
171
+
172
+ ```typescript
173
+ const outcome = await sdk.execute(pass, {
174
+ merchant: 'Shuttle Express',
175
+ amount: 18_500_000_000n, // 18.5 SUI in MIST
176
+ }, signer);
177
+
178
+ switch (outcome.status) {
179
+ case 'approved':
180
+ console.log('tx digest:', outcome.digest);
181
+ // audit receipt written to Walrus automatically
182
+ break;
183
+
184
+ case 'escalated':
185
+ // notify user — outcome.reason explains why
186
+ await sendPushNotification(outcome.reason);
187
+ // re-execute after user approves
188
+ break;
189
+
190
+ case 'blocked':
191
+ // policy rejected — outcome.reason explains why
192
+ console.log('blocked:', outcome.reason);
193
+ break;
194
+ }
195
+ ```
196
+
197
+ ---
198
+
199
+ ### `sdk.validate(pass, request)` → `PolicyValidation`
200
+
201
+ Preview the outcome without executing. Zero network calls. Sub-millisecond. Use for UI previews before execution.
202
+
203
+ ```typescript
204
+ const preview = sdk.validate(pass, {
205
+ merchant: 'Shuttle Express',
206
+ amount: 18_500_000_000n,
207
+ });
208
+
209
+ // { allowed: true, requiresEscalation: false, reason: 'Auto-approved' }
210
+ // { allowed: true, requiresEscalation: true, reason: 'Amount exceeds escalation threshold...' }
211
+ // { allowed: false, requiresEscalation: false, reason: 'Merchant "X" is not approved' }
212
+
213
+ if (!preview.allowed) {
214
+ showBlockedUI(preview.reason);
215
+ return;
216
+ }
217
+
218
+ if (preview.requiresEscalation) {
219
+ showEscalationUI(preview.reason);
220
+ return;
221
+ }
222
+
223
+ // Safe to execute
224
+ const outcome = await sdk.execute(pass, request, signer);
225
+ ```
226
+
227
+ ---
228
+
229
+ ### `sdk.revoke(pass, signer)` → `Promise<{ digest: string }>`
230
+
231
+ Revoke an EdgePass on-chain. All future `execute()` calls return `blocked` immediately.
232
+
233
+ ```typescript
234
+ const { digest } = await sdk.revoke(pass, signer);
235
+ console.log('revoked:', digest);
236
+ ```
237
+
238
+ ---
239
+
240
+ ### `sdk.fetch(objectId)` → `Promise<EdgePassObject | null>`
241
+
242
+ Fetch a live EdgePass from the Sui network.
243
+
244
+ ```typescript
245
+ const pass = await sdk.fetch('0x4e2f...8b91');
246
+
247
+ if (!pass) {
248
+ console.log('EdgePass not found');
249
+ return;
250
+ }
251
+
252
+ const remaining = sdk.remainingBudget(pass);
253
+ console.log('remaining:', remaining);
254
+ ```
255
+
256
+ ---
257
+
258
+ ### `sdk.remainingBudget(pass)` → `bigint`
259
+
260
+ Returns remaining budget in MIST.
261
+
262
+ ```typescript
263
+ const remaining = sdk.remainingBudget(pass);
264
+ const remainingSUI = Number(remaining) / Number(MIST_PER_SUI);
265
+ console.log(`$${remainingSUI.toFixed(2)} remaining`);
266
+ ```
267
+
268
+ ---
269
+
270
+ ### `sdk.isValid(pass)` → `boolean`
271
+
272
+ Returns `true` if the pass is active and not expired.
273
+
274
+ ```typescript
275
+ if (!sdk.isValid(pass)) {
276
+ // create a new pass
277
+ pass = await sdk.create(config, signer);
278
+ }
279
+ ```
280
+
281
+ ---
282
+
283
+ ## Templates
284
+
285
+ Pre-configured trust boundaries for common use cases. Every template is a starting point — override any field.
286
+
287
+ ```typescript
288
+ import { EdgePass, EDGE_TEMPLATES } from '@edge-protocol/sdk';
289
+
290
+ // Available templates
291
+ EdgePass.fromTemplate('festival', { owner }) // $300 / 48h
292
+ EdgePass.fromTemplate('gaming', { owner }) // $50 / 4h session
293
+ EdgePass.fromTemplate('subscription', { owner }) // $200 / 30 days
294
+ EdgePass.fromTemplate('defi', { owner }) // $10k / 7 days
295
+ EdgePass.fromTemplate('enterprise', { owner }) // $50k / 30 days
296
+ ```
297
+
298
+ ### Template defaults
299
+
300
+ | Template | Budget | Auto ≤ | Escalate ≥ | Max/tx | Expiry |
301
+ |----------|--------|--------|------------|--------|--------|
302
+ | `festival` | 300 SUI | 50 SUI | 100 SUI | 200 SUI | 48h |
303
+ | `gaming` | 50 SUI | 2 SUI | 10 SUI | 10 SUI | 4h |
304
+ | `subscription` | 200 SUI | 20 SUI | 50 SUI | 50 SUI | 30d |
305
+ | `defi` | 10,000 SUI | 500 SUI | 1,000 SUI | 2,000 SUI | 7d |
306
+ | `enterprise` | 50,000 SUI | 1,000 SUI | 5,000 SUI | 10,000 SUI | 30d |
307
+
308
+ ### Accessing raw template values
309
+
310
+ ```typescript
311
+ import { EDGE_TEMPLATES } from '@edge-protocol/sdk';
312
+
313
+ console.log(EDGE_TEMPLATES.festival.budget); // 300_000_000_000n
314
+ console.log(EDGE_TEMPLATES.defi.escalateThreshold); // 1_000_000_000_000n
315
+ ```
316
+
317
+ ---
318
+
319
+ ## PolicyEngine
320
+
321
+ Access the policy engine directly for custom validation flows.
322
+
323
+ ```typescript
324
+ import { PolicyEngine } from '@edge-protocol/sdk';
325
+ ```
326
+
327
+ ### `PolicyEngine.validate(pass, request)` → `PolicyValidation`
328
+
329
+ Validates a transaction request. Same logic used internally by `sdk.execute()`.
330
+
331
+ ```typescript
332
+ const validation = PolicyEngine.validate(pass, {
333
+ merchant: 'Shuttle Express',
334
+ amount: 18_500_000_000n,
335
+ });
336
+
337
+ // validation.allowed → boolean
338
+ // validation.requiresEscalation → boolean
339
+ // validation.reason → string
340
+ ```
341
+
342
+ **Validation rules (in order):**
343
+
344
+ 1. Pass must be active
345
+ 2. Pass must not be expired
346
+ 3. Merchant must be in `approvedMerchants`
347
+ 4. Amount must not exceed remaining budget
348
+ 5. Amount must not exceed `maxPerTransaction` (if set)
349
+ 6. If amount > `escalateThreshold` → escalate
350
+ 7. If amount ≤ `autoThreshold` → auto-approve
351
+
352
+ ### `PolicyEngine.isValid(pass)` → `boolean`
353
+
354
+ ```typescript
355
+ const valid = PolicyEngine.isValid(pass);
356
+ ```
357
+
358
+ ### `PolicyEngine.remainingBudget(pass)` → `bigint`
359
+
360
+ ```typescript
361
+ const remaining = PolicyEngine.remainingBudget(pass);
362
+ ```
363
+
364
+ ---
365
+
366
+ ## Types
367
+
368
+ ```typescript
369
+ import type {
370
+ EdgePassConfig,
371
+ EdgePassObject,
372
+ TransactionRequest,
373
+ TransactionOutcome,
374
+ PolicyValidation,
375
+ Network,
376
+ EdgeSDKConfig,
377
+ EdgePassTemplate,
378
+ } from '@edge-protocol/sdk';
379
+ ```
380
+
381
+ ### `EdgePassConfig`
382
+
383
+ ```typescript
384
+ interface EdgePassConfig {
385
+ budget: bigint; // total spend limit in MIST
386
+ autoThreshold: bigint; // auto-approve below this
387
+ escalateThreshold: bigint; // escalate above this
388
+ maxPerTransaction?: bigint; // optional hard cap per tx
389
+ approvedMerchants: string[]; // merchant allowlist
390
+ expiryMs: number; // duration in milliseconds
391
+ owner: string; // Sui address
392
+ }
393
+ ```
394
+
395
+ ### `EdgePassObject`
396
+
397
+ ```typescript
398
+ interface EdgePassObject {
399
+ id: string; // Sui object ID
400
+ config: EdgePassConfig;
401
+ spent: bigint; // total spent so far in MIST
402
+ active: boolean;
403
+ createdAt: number; // Unix timestamp
404
+ expiresAt: number; // Unix timestamp
405
+ }
406
+ ```
407
+
408
+ ### `TransactionRequest`
409
+
410
+ ```typescript
411
+ interface TransactionRequest {
412
+ merchant: string; // merchant identifier
413
+ amount: bigint; // amount in MIST
414
+ metadata?: Record<string, string>; // optional metadata
415
+ }
416
+ ```
417
+
418
+ ### `TransactionOutcome`
419
+
420
+ ```typescript
421
+ type TransactionOutcome =
422
+ | { status: 'approved'; digest: string; objectId?: string; auto: true }
423
+ | { status: 'escalated'; reason: string; auto: false }
424
+ | { status: 'blocked'; reason: string; auto: false };
425
+ ```
426
+
427
+ ### `PolicyValidation`
428
+
429
+ ```typescript
430
+ interface PolicyValidation {
431
+ allowed: boolean;
432
+ requiresEscalation: boolean;
433
+ reason: string;
434
+ }
435
+ ```
436
+
437
+ ### `Network`
438
+
439
+ ```typescript
440
+ type Network = 'mainnet' | 'testnet' | 'devnet';
441
+ ```
442
+
443
+ ### `EdgePassTemplate`
444
+
445
+ ```typescript
446
+ type EdgePassTemplate = 'festival' | 'gaming' | 'subscription' | 'defi' | 'enterprise';
447
+ ```
448
+
449
+ ---
450
+
451
+ ## Constants
452
+
453
+ ```typescript
454
+ import {
455
+ MIST_PER_SUI, // 1_000_000_000n
456
+ NETWORK_URLS, // { mainnet, testnet, devnet }
457
+ EDGE_PACKAGE_ID, // { mainnet, testnet, devnet }
458
+ EDGE_TEMPLATES, // all 5 templates
459
+ DEFAULT_GAS_BUDGET // 10_000_000n
460
+ } from '@edge-protocol/sdk';
461
+ ```
462
+
463
+ ---
464
+
465
+ ## Integration Examples
466
+
467
+ ### AI Agent with EdgePass
468
+
469
+ A Claude LLM making autonomous festival purchases within an EdgePass.
470
+
471
+ ```typescript
472
+ import { EdgePass, MIST_PER_SUI } from '@edge-protocol/sdk';
473
+ import Anthropic from '@anthropic-ai/sdk';
474
+
475
+ const sdk = new EdgePass({ network: 'mainnet', enokiApiKey: KEY });
476
+ const claude = new Anthropic();
477
+
478
+ // 1. User creates EdgePass once
479
+ const pass = await sdk.create(
480
+ EdgePass.fromTemplate('festival', {
481
+ approvedMerchants: ['Shuttle Express', 'Hydra Bar', 'Stage Access VIP'],
482
+ owner: userAddress,
483
+ }),
484
+ signer
485
+ );
486
+
487
+ // 2. Agent loop — runs autonomously
488
+ async function agentLoop(scenario: string) {
489
+ const response = await claude.messages.create({
490
+ model: 'claude-sonnet-4-6',
491
+ max_tokens: 500,
492
+ messages: [{
493
+ role: 'user',
494
+ content: `Festival scenario: "${scenario}".
495
+ Decide what to purchase. Return JSON:
496
+ { merchant: string, amount: number }`
497
+ }]
498
+ });
499
+
500
+ const { merchant, amount } = JSON.parse(response.content[0].text);
501
+
502
+ const outcome = await sdk.execute(pass, {
503
+ merchant,
504
+ amount: BigInt(Math.floor(amount * 1e9)),
505
+ }, signer);
506
+
507
+ if (outcome.status === 'escalated') {
508
+ await notifyUser(`Approve $${amount} at ${merchant}?`);
509
+ }
510
+
511
+ return outcome;
512
+ }
513
+ ```
514
+
515
+ ---
516
+
517
+ ### DeFi Trading Agent
518
+
519
+ ```typescript
520
+ const pass = await sdk.create(
521
+ EdgePass.fromTemplate('defi', {
522
+ approvedMerchants: ['DeepBook', 'Cetus', 'Turbos'],
523
+ budget: 5_000n * MIST_PER_SUI,
524
+ owner: userAddress,
525
+ }),
526
+ signer
527
+ );
528
+
529
+ async function executeTrade(dex: string, amount: bigint) {
530
+ // validate before network call
531
+ const preview = sdk.validate(pass, { merchant: dex, amount });
532
+
533
+ if (!preview.allowed) {
534
+ logger.warn(`Trade blocked: ${preview.reason}`);
535
+ return;
536
+ }
537
+
538
+ if (preview.requiresEscalation) {
539
+ await riskTeam.requestApproval({ dex, amount, reason: preview.reason });
540
+ return;
541
+ }
542
+
543
+ const outcome = await sdk.execute(pass, { merchant: dex, amount }, signer);
544
+ // audit log written to Walrus automatically
545
+ logger.info(`Trade executed: ${outcome.digest}`);
546
+ }
547
+ ```
548
+
549
+ ---
550
+
551
+ ### Enterprise Payroll Agent
552
+
553
+ ```typescript
554
+ const pass = await sdk.create(
555
+ EdgePass.fromTemplate('enterprise', {
556
+ approvedMerchants: ['vendor-a.sui', 'vendor-b.sui'],
557
+ budget: 100_000n * MIST_PER_SUI,
558
+ escalateThreshold: 10_000n * MIST_PER_SUI,
559
+ owner: cfoAddress,
560
+ }),
561
+ signer
562
+ );
563
+
564
+ for (const payment of scheduledPayments) {
565
+ const outcome = await sdk.execute(pass, {
566
+ merchant: payment.vendor,
567
+ amount: payment.amount,
568
+ }, signer);
569
+
570
+ if (outcome.status === 'escalated') {
571
+ await cfo.requestApproval(payment); // new vendor or large amount
572
+ }
573
+ // every payment logged to Walrus for compliance audit
574
+ }
575
+ ```
576
+
577
+ ---
578
+
579
+ ### Subscription Manager
580
+
581
+ ```typescript
582
+ const pass = await sdk.create(
583
+ EdgePass.fromTemplate('subscription', {
584
+ approvedMerchants: ['netflix.sui', 'spotify.sui', 'github.sui'],
585
+ owner: userAddress,
586
+ }),
587
+ signer
588
+ );
589
+
590
+ // Runs monthly — agent handles all renewals
591
+ async function processRenewals(subscriptions: Subscription[]) {
592
+ for (const sub of subscriptions) {
593
+ if (!sdk.isValid(pass)) {
594
+ pass = await sdk.create(
595
+ EdgePass.fromTemplate('subscription', { owner: userAddress }),
596
+ signer
597
+ );
598
+ }
599
+
600
+ await sdk.execute(pass, {
601
+ merchant: sub.merchant,
602
+ amount: sub.amount,
603
+ }, signer);
604
+ }
605
+ }
606
+ ```
607
+
608
+ ---
609
+
610
+ ## Error Handling
611
+
612
+ ```typescript
613
+ try {
614
+ const outcome = await sdk.execute(pass, request, signer);
615
+
616
+ switch (outcome.status) {
617
+ case 'approved':
618
+ // success — outcome.digest is the Sui tx hash
619
+ break;
620
+ case 'escalated':
621
+ // needs human review — outcome.reason explains why
622
+ break;
623
+ case 'blocked':
624
+ // policy rejected — outcome.reason explains why
625
+ break;
626
+ }
627
+ } catch (error) {
628
+ // network error, signing failure, expired credentials, etc.
629
+ console.error('SDK error:', error);
630
+ }
631
+ ```
632
+
633
+ ### Common reasons
634
+
635
+ | Reason | Cause |
636
+ |--------|-------|
637
+ | `EdgePass is inactive` | Pass was revoked |
638
+ | `EdgePass has expired` | `expiresAt` timestamp passed |
639
+ | `Merchant "X" is not approved` | Merchant not in allowlist |
640
+ | `Insufficient budget` | Remaining budget < amount |
641
+ | `Amount exceeds per-transaction limit` | Amount > `maxPerTransaction` |
642
+ | `Amount exceeds escalation threshold` | Amount > `escalateThreshold` (not blocked — escalated) |
643
+
644
+ ---
645
+
646
+ ## Architecture
647
+
648
+ ```
649
+ User creates EdgePass (once)
650
+
651
+
652
+ Agent calls sdk.execute() — many times, autonomously
653
+
654
+ ├─▶ PolicyEngine.validate()
655
+ │ Pure TypeScript · no network · <1ms
656
+ │ 7 rules checked in order
657
+ │ blocked/escalated never touch Sui
658
+
659
+ ├─▶ ExecutionEngine.buildPTB()
660
+ │ Programmable Transaction Block
661
+ │ validate → execute → update spent → emit event
662
+ │ atomic — any failure reverts everything
663
+
664
+ └─▶ Walrus audit receipt
665
+ immutable · decentralized · permanent
666
+ ```
667
+
668
+ ### Why PTBs matter
669
+
670
+ PTBs (Programmable Transaction Blocks) are Sui's killer feature. The policy check and the spend update happen in one atomic block. If any step fails, everything reverts. No partial state. No race conditions. This is what makes EdgePass trustworthy at the protocol level — not just application code.
671
+
672
+ ### Why the object model matters
673
+
674
+ The EdgePass is a first-class owned object in the user's wallet. An agent can be passed the object to execute against — but the Sui protocol guarantees it can never take ownership. No contract upgrade, no admin key, no reentrancy attack can change that.
675
+
676
+ ---
677
+
678
+ ## Move Contract
679
+
680
+ ```
681
+ Package: 0x9f4065009494aa5acd92a5c72a6c22ce80939b2bddae3b34345459bc98d2501d
682
+ Network: Sui Testnet (Mainnet coming)
683
+ ```
684
+
685
+ [View on Sui Explorer →](https://suiscan.xyz/testnet/object/0x9f4065009494aa5acd92a5c72a6c22ce80939b2bddae3b34345459bc98d2501d)
686
+
687
+ ### Contract functions
688
+
689
+ ```move
690
+ // Create a new EdgePass
691
+ public entry fun create_pass(
692
+ budget: u64,
693
+ auto_threshold: u64,
694
+ escalate_threshold: u64,
695
+ expiry_ms: u64,
696
+ approved_merchants: vector<String>,
697
+ clock: &Clock,
698
+ ctx: &mut TxContext,
699
+ )
700
+
701
+ // Execute a transaction against an EdgePass
702
+ public entry fun execute_transaction(
703
+ pass: &mut EdgePass,
704
+ amount: u64,
705
+ merchant: String,
706
+ clock: &Clock,
707
+ ctx: &mut TxContext,
708
+ )
709
+
710
+ // Revoke an EdgePass
711
+ public entry fun revoke_pass(
712
+ pass: &mut EdgePass,
713
+ ctx: &mut TxContext,
714
+ )
715
+ ```
716
+
717
+ ---
718
+
719
+ ## Testing
720
+
721
+ ```bash
722
+ cd packages/sdk && pnpm test
723
+ ```
724
+
725
+ ```
726
+ 📋 PolicyEngine.validate()
727
+ ✓ auto-approves under $50
728
+ ✓ auto-approves at exactly $50
729
+ ✓ escalates above $100
730
+ ✓ escalates at exactly $101
731
+ ✓ blocks unlisted merchant
732
+ ✓ blocks when budget exceeded
733
+ ✓ blocks when expired
734
+ ✓ blocks when inactive
735
+ ✓ blocks when maxPerTransaction exceeded
736
+ ✓ allows when maxPerTransaction is undefined
737
+
738
+ 📋 PolicyEngine helpers
739
+ ✓ isValid returns true for active pass
740
+ ✓ isValid returns false for expired pass
741
+ ✓ isValid returns false for inactive pass
742
+ ✓ remainingBudget calculates correctly
743
+ ✓ remainingBudget returns full budget when nothing spent
744
+
745
+ 📋 EdgePass.fromTemplate()
746
+ ✓ festival template has correct defaults
747
+ ✓ gaming template has correct expiry
748
+ ✓ defi template has correct budget
749
+ ✓ enterprise template has correct budget
750
+ ✓ fromTemplate allows budget override
751
+ ✓ fromTemplate allows merchant override
752
+ ✓ fromTemplate preserves owner
753
+
754
+ 📋 Constants
755
+ ✓ MIST_PER_SUI is 1_000_000_000
756
+ ✓ all 5 templates exist
757
+ ✓ all templates have required fields
758
+ ✓ all templates have autoThreshold < escalateThreshold
759
+ ✓ all templates have escalateThreshold < budget
760
+
761
+ 27 passed · 0 failed ✅
762
+ ```
763
+
764
+ ---
765
+
766
+ ## Links
767
+
768
+ - **npm:** [npmjs.com/package/@edge-protocol/sdk](https://npmjs.com/package/@edge-protocol/sdk)
769
+ - **GitHub:** [github.com/fluturecode/edge](https://github.com/fluturecode/edge)
770
+ - **Live Demo:** [edge-web-cyan.vercel.app](https://edge-web-cyan.vercel.app)
771
+ - **Sui Explorer:** [Contract on Testnet](https://suiscan.xyz/testnet/object/0x9f4065009494aa5acd92a5c72a6c22ce80939b2bddae3b34345459bc98d2501d)
772
+
773
+ ---
774
+
775
+ *The best infrastructure is invisible.*
776
+
777
+ Built for [Sui Overflow 2026](https://overflow.sui.io) · MIT License
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@edge-protocol/sdk",
3
- "version": "0.4.6",
3
+ "version": "0.4.7",
4
4
  "description": "Programmable trust infrastructure for autonomous AI agents on Sui. Give agents your rules, not your keys.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",