@agent-fuel/sdk 0.1.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -63,7 +63,8 @@ function decodeCreditVault(pubkey, raw) {
63
63
  balance: total_deposited - total_withdrawn - total_spent + total_claimed,
64
64
  frozen: raw.frozen,
65
65
  created_slot: bnToNum(raw.createdSlot),
66
- last_active_slot: bnToNum(raw.lastActiveSlot)
66
+ last_active_slot: bnToNum(raw.lastActiveSlot),
67
+ pending_count: bnToNum(raw.pendingCount)
67
68
  };
68
69
  }
69
70
  var DEFAULT_PUBKEY = web3_js.PublicKey.default.toBase58();
@@ -1953,6 +1954,200 @@ var credit_vault_default = {
1953
1954
  repository: "https://github.com/TODO/agent_fuel"
1954
1955
  },
1955
1956
  instructions: [
1957
+ {
1958
+ name: "approve_spend",
1959
+ discriminator: [
1960
+ 248,
1961
+ 201,
1962
+ 151,
1963
+ 15,
1964
+ 28,
1965
+ 162,
1966
+ 112,
1967
+ 90
1968
+ ],
1969
+ accounts: [
1970
+ {
1971
+ name: "owner",
1972
+ writable: true,
1973
+ signer: true,
1974
+ relations: [
1975
+ "vault"
1976
+ ]
1977
+ },
1978
+ {
1979
+ name: "vault",
1980
+ writable: true,
1981
+ pda: {
1982
+ seeds: [
1983
+ {
1984
+ kind: "const",
1985
+ value: [
1986
+ 118,
1987
+ 97,
1988
+ 117,
1989
+ 108,
1990
+ 116
1991
+ ]
1992
+ },
1993
+ {
1994
+ kind: "account",
1995
+ path: "owner"
1996
+ },
1997
+ {
1998
+ kind: "account",
1999
+ path: "vault.agent",
2000
+ account: "CreditVault"
2001
+ }
2002
+ ]
2003
+ }
2004
+ },
2005
+ {
2006
+ name: "policy",
2007
+ writable: true,
2008
+ pda: {
2009
+ seeds: [
2010
+ {
2011
+ kind: "const",
2012
+ value: [
2013
+ 112,
2014
+ 111,
2015
+ 108,
2016
+ 105,
2017
+ 99,
2018
+ 121
2019
+ ]
2020
+ },
2021
+ {
2022
+ kind: "account",
2023
+ path: "vault"
2024
+ }
2025
+ ]
2026
+ }
2027
+ },
2028
+ {
2029
+ name: "pending_spend",
2030
+ writable: true,
2031
+ pda: {
2032
+ seeds: [
2033
+ {
2034
+ kind: "const",
2035
+ value: [
2036
+ 112,
2037
+ 101,
2038
+ 110,
2039
+ 100,
2040
+ 105,
2041
+ 110,
2042
+ 103
2043
+ ]
2044
+ },
2045
+ {
2046
+ kind: "account",
2047
+ path: "vault"
2048
+ },
2049
+ {
2050
+ kind: "account",
2051
+ path: "pending_spend.nonce",
2052
+ account: "PendingSpend"
2053
+ }
2054
+ ]
2055
+ }
2056
+ },
2057
+ {
2058
+ name: "vault_token_account",
2059
+ writable: true
2060
+ },
2061
+ {
2062
+ name: "service_token_account",
2063
+ writable: true
2064
+ },
2065
+ {
2066
+ name: "token_program",
2067
+ address: "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
2068
+ }
2069
+ ],
2070
+ args: []
2071
+ },
2072
+ {
2073
+ name: "cancel_spend",
2074
+ discriminator: [
2075
+ 122,
2076
+ 254,
2077
+ 101,
2078
+ 132,
2079
+ 241,
2080
+ 232,
2081
+ 205,
2082
+ 179
2083
+ ],
2084
+ accounts: [
2085
+ {
2086
+ name: "owner",
2087
+ writable: true,
2088
+ signer: true,
2089
+ relations: [
2090
+ "vault"
2091
+ ]
2092
+ },
2093
+ {
2094
+ name: "vault",
2095
+ pda: {
2096
+ seeds: [
2097
+ {
2098
+ kind: "const",
2099
+ value: [
2100
+ 118,
2101
+ 97,
2102
+ 117,
2103
+ 108,
2104
+ 116
2105
+ ]
2106
+ },
2107
+ {
2108
+ kind: "account",
2109
+ path: "owner"
2110
+ },
2111
+ {
2112
+ kind: "account",
2113
+ path: "vault.agent",
2114
+ account: "CreditVault"
2115
+ }
2116
+ ]
2117
+ }
2118
+ },
2119
+ {
2120
+ name: "pending_spend",
2121
+ writable: true,
2122
+ pda: {
2123
+ seeds: [
2124
+ {
2125
+ kind: "const",
2126
+ value: [
2127
+ 112,
2128
+ 101,
2129
+ 110,
2130
+ 100,
2131
+ 105,
2132
+ 110,
2133
+ 103
2134
+ ]
2135
+ },
2136
+ {
2137
+ kind: "account",
2138
+ path: "vault"
2139
+ },
2140
+ {
2141
+ kind: "account",
2142
+ path: "pending_spend.nonce",
2143
+ account: "PendingSpend"
2144
+ }
2145
+ ]
2146
+ }
2147
+ }
2148
+ ],
2149
+ args: []
2150
+ },
1956
2151
  {
1957
2152
  name: "claim",
1958
2153
  discriminator: [
@@ -2359,6 +2554,104 @@ var credit_vault_default = {
2359
2554
  ],
2360
2555
  args: []
2361
2556
  },
2557
+ {
2558
+ name: "request_spend",
2559
+ discriminator: [
2560
+ 127,
2561
+ 12,
2562
+ 23,
2563
+ 75,
2564
+ 137,
2565
+ 178,
2566
+ 148,
2567
+ 71
2568
+ ],
2569
+ accounts: [
2570
+ {
2571
+ name: "agent",
2572
+ writable: true,
2573
+ signer: true,
2574
+ relations: [
2575
+ "vault"
2576
+ ]
2577
+ },
2578
+ {
2579
+ name: "vault",
2580
+ writable: true,
2581
+ pda: {
2582
+ seeds: [
2583
+ {
2584
+ kind: "const",
2585
+ value: [
2586
+ 118,
2587
+ 97,
2588
+ 117,
2589
+ 108,
2590
+ 116
2591
+ ]
2592
+ },
2593
+ {
2594
+ kind: "account",
2595
+ path: "vault.owner",
2596
+ account: "CreditVault"
2597
+ },
2598
+ {
2599
+ kind: "account",
2600
+ path: "vault.agent",
2601
+ account: "CreditVault"
2602
+ }
2603
+ ]
2604
+ }
2605
+ },
2606
+ {
2607
+ name: "service_token_account",
2608
+ docs: [
2609
+ "The recipient token account. We only need it for its `owner` field",
2610
+ "(the service pubkey we record in PendingSpend); mint constraint is",
2611
+ "belt-and-suspenders since `approve_spend` re-checks both."
2612
+ ]
2613
+ },
2614
+ {
2615
+ name: "pending_spend",
2616
+ writable: true,
2617
+ pda: {
2618
+ seeds: [
2619
+ {
2620
+ kind: "const",
2621
+ value: [
2622
+ 112,
2623
+ 101,
2624
+ 110,
2625
+ 100,
2626
+ 105,
2627
+ 110,
2628
+ 103
2629
+ ]
2630
+ },
2631
+ {
2632
+ kind: "account",
2633
+ path: "vault"
2634
+ },
2635
+ {
2636
+ kind: "account",
2637
+ path: "vault.pending_count",
2638
+ account: "CreditVault"
2639
+ }
2640
+ ]
2641
+ }
2642
+ },
2643
+ {
2644
+ name: "system_program",
2645
+ address: "11111111111111111111111111111111"
2646
+ }
2647
+ ],
2648
+ args: [
2649
+ {
2650
+ name: "amount_usdc",
2651
+ type: "u64"
2652
+ }
2653
+ ]
2654
+ },
2362
2655
  {
2363
2656
  name: "spend",
2364
2657
  discriminator: [
@@ -2684,6 +2977,19 @@ var credit_vault_default = {
2684
2977
  70
2685
2978
  ]
2686
2979
  },
2980
+ {
2981
+ name: "PendingSpend",
2982
+ discriminator: [
2983
+ 193,
2984
+ 205,
2985
+ 85,
2986
+ 66,
2987
+ 25,
2988
+ 3,
2989
+ 67,
2990
+ 134
2991
+ ]
2992
+ },
2687
2993
  {
2688
2994
  name: "SpendPolicy",
2689
2995
  discriminator: [
@@ -2738,6 +3044,32 @@ var credit_vault_default = {
2738
3044
  161
2739
3045
  ]
2740
3046
  },
3047
+ {
3048
+ name: "SpendRejected",
3049
+ discriminator: [
3050
+ 22,
3051
+ 233,
3052
+ 208,
3053
+ 109,
3054
+ 202,
3055
+ 231,
3056
+ 175,
3057
+ 22
3058
+ ]
3059
+ },
3060
+ {
3061
+ name: "SpendRequested",
3062
+ discriminator: [
3063
+ 144,
3064
+ 207,
3065
+ 254,
3066
+ 247,
3067
+ 81,
3068
+ 146,
3069
+ 84,
3070
+ 87
3071
+ ]
3072
+ },
2741
3073
  {
2742
3074
  name: "Spent",
2743
3075
  discriminator: [
@@ -2854,6 +3186,16 @@ var credit_vault_default = {
2854
3186
  code: 6009,
2855
3187
  name: "PostPayDisabled",
2856
3188
  msg: "Post-pay claims are disabled for this vault"
3189
+ },
3190
+ {
3191
+ code: 6010,
3192
+ name: "PendingSpendVaultMismatch",
3193
+ msg: "Pending spend belongs to a different vault"
3194
+ },
3195
+ {
3196
+ code: 6011,
3197
+ name: "PendingNonceOverflow",
3198
+ msg: "Pending spend counter would overflow"
2857
3199
  }
2858
3200
  ],
2859
3201
  types: [
@@ -2942,12 +3284,22 @@ var credit_vault_default = {
2942
3284
  name: "bump",
2943
3285
  type: "u8"
2944
3286
  },
3287
+ {
3288
+ name: "pending_count",
3289
+ docs: [
3290
+ "Monotonic counter used as a PDA seed for PendingSpend accounts so",
3291
+ "every approval request gets a unique deterministic address.",
3292
+ "Borrowed 8 bytes from the original 64-byte padding so the account",
3293
+ "size stays at `ACCOUNT_SIZE` and existing vaults need no migration."
3294
+ ],
3295
+ type: "u64"
3296
+ },
2945
3297
  {
2946
3298
  name: "_padding",
2947
3299
  type: {
2948
3300
  array: [
2949
3301
  "u8",
2950
- 64
3302
+ 56
2951
3303
  ]
2952
3304
  }
2953
3305
  }
@@ -2982,6 +3334,65 @@ var credit_vault_default = {
2982
3334
  ]
2983
3335
  }
2984
3336
  },
3337
+ {
3338
+ name: "PendingSpend",
3339
+ docs: [
3340
+ "A spend request that exceeded one of the policy's rate limits. The agent",
3341
+ "creates this account by calling `request_spend`; the owner reviews from",
3342
+ "the mobile Alerts tab and either calls `approve_spend` (PDA-signed CPI",
3343
+ "transfer, account closed) or `cancel_spend` (account closed, no transfer).",
3344
+ "",
3345
+ 'Seeded by `["pending", vault, nonce_le]` where `nonce` is the value of',
3346
+ "`vault.pending_count` at request time, so each request has a unique",
3347
+ "deterministic address that both the agent and the owner can derive."
3348
+ ],
3349
+ type: {
3350
+ kind: "struct",
3351
+ fields: [
3352
+ {
3353
+ name: "vault",
3354
+ type: "pubkey"
3355
+ },
3356
+ {
3357
+ name: "agent",
3358
+ type: "pubkey"
3359
+ },
3360
+ {
3361
+ name: "service",
3362
+ docs: [
3363
+ "Owner of the destination token account (mirrors how `Spent` records",
3364
+ "service: `service_token_account.owner`)."
3365
+ ],
3366
+ type: "pubkey"
3367
+ },
3368
+ {
3369
+ name: "amount_usdc",
3370
+ type: "u64"
3371
+ },
3372
+ {
3373
+ name: "requested_slot",
3374
+ type: "u64"
3375
+ },
3376
+ {
3377
+ name: "nonce",
3378
+ type: "u64"
3379
+ },
3380
+ {
3381
+ name: "bump",
3382
+ type: "u8"
3383
+ },
3384
+ {
3385
+ name: "_padding",
3386
+ type: {
3387
+ array: [
3388
+ "u8",
3389
+ 31
3390
+ ]
3391
+ }
3392
+ }
3393
+ ]
3394
+ }
3395
+ },
2985
3396
  {
2986
3397
  name: "PolicyUpdated",
2987
3398
  type: {
@@ -3085,6 +3496,70 @@ var credit_vault_default = {
3085
3496
  ]
3086
3497
  }
3087
3498
  },
3499
+ {
3500
+ name: "SpendRejected",
3501
+ type: {
3502
+ kind: "struct",
3503
+ fields: [
3504
+ {
3505
+ name: "vault",
3506
+ type: "pubkey"
3507
+ },
3508
+ {
3509
+ name: "owner",
3510
+ type: "pubkey"
3511
+ },
3512
+ {
3513
+ name: "pending_spend",
3514
+ type: "pubkey"
3515
+ },
3516
+ {
3517
+ name: "nonce",
3518
+ type: "u64"
3519
+ },
3520
+ {
3521
+ name: "slot",
3522
+ type: "u64"
3523
+ }
3524
+ ]
3525
+ }
3526
+ },
3527
+ {
3528
+ name: "SpendRequested",
3529
+ type: {
3530
+ kind: "struct",
3531
+ fields: [
3532
+ {
3533
+ name: "vault",
3534
+ type: "pubkey"
3535
+ },
3536
+ {
3537
+ name: "agent",
3538
+ type: "pubkey"
3539
+ },
3540
+ {
3541
+ name: "service",
3542
+ type: "pubkey"
3543
+ },
3544
+ {
3545
+ name: "pending_spend",
3546
+ type: "pubkey"
3547
+ },
3548
+ {
3549
+ name: "amount_usdc",
3550
+ type: "u64"
3551
+ },
3552
+ {
3553
+ name: "nonce",
3554
+ type: "u64"
3555
+ },
3556
+ {
3557
+ name: "slot",
3558
+ type: "u64"
3559
+ }
3560
+ ]
3561
+ }
3562
+ },
3088
3563
  {
3089
3564
  name: "Spent",
3090
3565
  type: {
@@ -3269,6 +3744,15 @@ function agentServiceLinkPda(agentProfile, serviceRegistry) {
3269
3744
  );
3270
3745
  return pda;
3271
3746
  }
3747
+ function pendingSpendPda(vault, nonce) {
3748
+ const nonceBuf = Buffer.alloc(8);
3749
+ nonceBuf.writeBigUInt64LE(typeof nonce === "bigint" ? nonce : BigInt(nonce));
3750
+ const [pda] = web3_js.PublicKey.findProgramAddressSync(
3751
+ [Buffer.from("pending"), toPubkey(vault).toBuffer(), nonceBuf],
3752
+ PROGRAM_IDS.creditVault
3753
+ );
3754
+ return pda;
3755
+ }
3272
3756
  function receiptUsedPda(receiptHash) {
3273
3757
  if (receiptHash.length !== 32) {
3274
3758
  throw new Error(`receiptUsedPda expects a 32-byte hash, got ${receiptHash.length}`);
@@ -3289,6 +3773,207 @@ function reputationProgram(provider) {
3289
3773
  return new anchor.Program(reputation_default, provider);
3290
3774
  }
3291
3775
 
3776
+ // src/pay.ts
3777
+ async function pay(args) {
3778
+ const { agent, service, connection, amountUsdc } = args;
3779
+ const owner = toPubkey(args.owner);
3780
+ if (amountUsdc <= 0) {
3781
+ throw new ZeroAmountError();
3782
+ }
3783
+ if (args.receiptHash.length !== 32) {
3784
+ throw new Error(
3785
+ `pay: receiptHash must be 32 bytes, got ${args.receiptHash.length}`
3786
+ );
3787
+ }
3788
+ const vaultAddr = vaultPda(owner, agent.publicKey);
3789
+ const policyAddr = policyPda(vaultAddr);
3790
+ const provider = buildProvider(connection, agent);
3791
+ const cv = creditVaultProgram(provider);
3792
+ const rep = reputationProgram(provider);
3793
+ const [rawVault, rawPolicy, currentSlot] = await Promise.all([
3794
+ cv.account.creditVault.fetchNullable(vaultAddr),
3795
+ cv.account.spendPolicy.fetchNullable(policyAddr),
3796
+ connection.getSlot()
3797
+ ]);
3798
+ if (!rawVault) throw new AccountNotFoundError(vaultAddr.toBase58());
3799
+ if (!rawPolicy) throw new AccountNotFoundError(policyAddr.toBase58());
3800
+ const vault = decodeCreditVault(vaultAddr, rawVault);
3801
+ const policy = decodeSpendPolicy(policyAddr, rawPolicy);
3802
+ guardSpend({
3803
+ vault,
3804
+ policy,
3805
+ service: service.publicKey,
3806
+ amountUsdc,
3807
+ currentSlot
3808
+ });
3809
+ const serviceTokenAccount = getAssociatedTokenAddress(
3810
+ vault.usdc_mint,
3811
+ service.publicKey
3812
+ );
3813
+ const createAtaIx = createAssociatedTokenAccountIdempotentInstruction(
3814
+ agent.publicKey,
3815
+ serviceTokenAccount,
3816
+ service.publicKey,
3817
+ vault.usdc_mint
3818
+ );
3819
+ const agentProfile = agentProfilePda(agent.publicKey);
3820
+ const serviceRegistry = serviceRegistryPda(service.publicKey);
3821
+ const link = agentServiceLinkPda(agentProfile, serviceRegistry);
3822
+ const receipt = receiptUsedPda(args.receiptHash);
3823
+ const spendBuilder = cv.methods.spend(new anchor.BN(amountUsdc)).accounts({
3824
+ agent: agent.publicKey,
3825
+ vault: vaultAddr,
3826
+ policy: policyAddr,
3827
+ vaultTokenAccount: vault.vault_token_account,
3828
+ serviceTokenAccount,
3829
+ tokenProgram: TOKEN_PROGRAM_ID
3830
+ });
3831
+ const recordBuilder = rep.methods.recordPayment(new anchor.BN(amountUsdc), args.receiptHash).accounts({
3832
+ service: service.publicKey,
3833
+ agentProfile,
3834
+ serviceRegistry,
3835
+ agentServiceLink: link,
3836
+ receiptUsed: receipt,
3837
+ systemProgram: web3_js.SystemProgram.programId
3838
+ });
3839
+ const spendIx = await spendBuilder.instruction();
3840
+ const recordIx = await recordBuilder.instruction();
3841
+ const tx = new web3_js.Transaction().add(createAtaIx, spendIx, recordIx);
3842
+ try {
3843
+ const signature = await web3_js.sendAndConfirmTransaction(
3844
+ connection,
3845
+ tx,
3846
+ [agent, service],
3847
+ { commitment: "confirmed" }
3848
+ );
3849
+ return { signature };
3850
+ } catch (err) {
3851
+ throw mapPayError(err, {
3852
+ service: service.publicKey,
3853
+ amountUsdc,
3854
+ vault,
3855
+ policy,
3856
+ receiptHash: args.receiptHash
3857
+ });
3858
+ }
3859
+ }
3860
+ function mapPayError(err, ctx) {
3861
+ const message = err instanceof Error ? err.message : String(err);
3862
+ if (/already in use/i.test(message)) {
3863
+ return new ReceiptAlreadyRecordedError(ctx.receiptHash);
3864
+ }
3865
+ if (!(err instanceof anchor.AnchorError)) return err;
3866
+ switch (err.error.errorCode.number) {
3867
+ case 6001:
3868
+ return new ZeroAmountError();
3869
+ case 6002:
3870
+ return new VaultFrozenError();
3871
+ case 6003:
3872
+ return new NotWhitelistedError(ctx.service.toBase58());
3873
+ case 6004:
3874
+ return new PerTxLimitExceededError(ctx.amountUsdc, ctx.policy.per_tx_limit_usdc);
3875
+ case 6005:
3876
+ return new HourlyLimitExceededError(
3877
+ ctx.amountUsdc,
3878
+ ctx.policy.hourly_window_spent_usdc,
3879
+ ctx.policy.hourly_limit_usdc
3880
+ );
3881
+ case 6006:
3882
+ return new LifetimeLimitExceededError(
3883
+ ctx.amountUsdc,
3884
+ ctx.vault.total_spent,
3885
+ ctx.policy.lifetime_limit_usdc
3886
+ );
3887
+ // Reputation errors:
3888
+ case 6e3:
3889
+ return new RecordPaymentError("counter overflow on chain");
3890
+ case 6011:
3891
+ return new ServiceInactiveError(ctx.service.toBase58());
3892
+ default:
3893
+ return err;
3894
+ }
3895
+ }
3896
+ async function requestSpend(args) {
3897
+ const { agent, connection, amountUsdc } = args;
3898
+ const owner = toPubkey(args.owner);
3899
+ const service = toPubkey(args.service);
3900
+ if (amountUsdc <= 0) {
3901
+ throw new Error("requestSpend: amountUsdc must be > 0");
3902
+ }
3903
+ const vaultAddr = vaultPda(owner, agent.publicKey);
3904
+ const provider = buildProvider(connection, agent);
3905
+ const cv = creditVaultProgram(provider);
3906
+ const rawVault = await cv.account.creditVault.fetchNullable(vaultAddr);
3907
+ if (!rawVault) throw new AccountNotFoundError(vaultAddr.toBase58());
3908
+ const vault = decodeCreditVault(vaultAddr, rawVault);
3909
+ const nonce = vault.pending_count;
3910
+ const pendingSpend = pendingSpendPda(vaultAddr, nonce);
3911
+ const serviceTokenAccount = getAssociatedTokenAddress(
3912
+ vault.usdc_mint,
3913
+ service
3914
+ );
3915
+ const signature = await cv.methods.requestSpend(new anchor.BN(amountUsdc)).accounts({
3916
+ agent: agent.publicKey,
3917
+ vault: vaultAddr,
3918
+ serviceTokenAccount,
3919
+ pendingSpend,
3920
+ systemProgram: web3_js.SystemProgram.programId
3921
+ }).signers([agent]).rpc();
3922
+ return { signature, pendingSpend, nonce };
3923
+ }
3924
+ var NAME_BYTES = 32;
3925
+ var URI_BYTES = 128;
3926
+ async function registerService(args) {
3927
+ const { sponsor, service, connection } = args;
3928
+ if (args.name.length === 0) {
3929
+ throw new Error("registerService: name must not be empty");
3930
+ }
3931
+ if (Buffer.byteLength(args.name, "utf8") > NAME_BYTES) {
3932
+ throw new Error(
3933
+ `registerService: name exceeds ${NAME_BYTES} bytes (got ${Buffer.byteLength(args.name, "utf8")})`
3934
+ );
3935
+ }
3936
+ const uri = args.serviceUri ?? "";
3937
+ if (Buffer.byteLength(uri, "utf8") > URI_BYTES) {
3938
+ throw new Error(
3939
+ `registerService: serviceUri exceeds ${URI_BYTES} bytes (got ${Buffer.byteLength(uri, "utf8")})`
3940
+ );
3941
+ }
3942
+ const registry = serviceRegistryPda(service.publicKey);
3943
+ const provider = buildProvider(connection, sponsor);
3944
+ const rep = reputationProgram(provider);
3945
+ const signature = await rep.methods.registerService(
3946
+ packFixed(args.name, NAME_BYTES),
3947
+ categoryArg(args.category),
3948
+ packFixed(uri, URI_BYTES)
3949
+ ).accounts({
3950
+ sponsor: sponsor.publicKey,
3951
+ service: service.publicKey,
3952
+ serviceRegistry: registry,
3953
+ systemProgram: web3_js.SystemProgram.programId
3954
+ }).signers([sponsor, service]).rpc();
3955
+ return { signature };
3956
+ }
3957
+ function packFixed(s, length) {
3958
+ const buf = Buffer.alloc(length);
3959
+ buf.write(s, 0, "utf8");
3960
+ return Array.from(buf);
3961
+ }
3962
+ function categoryArg(c) {
3963
+ switch (c) {
3964
+ case "DataFeed":
3965
+ return { dataFeed: {} };
3966
+ case "Compute":
3967
+ return { compute: {} };
3968
+ case "Swap":
3969
+ return { swap: {} };
3970
+ case "Rpc":
3971
+ return { rpc: {} };
3972
+ case "Other":
3973
+ return { other: {} };
3974
+ }
3975
+ }
3976
+
3292
3977
  // src/client.ts
3293
3978
  var DEFAULT_API_BASE = "http://localhost:8080";
3294
3979
  var AgentFuel = class {
@@ -3387,6 +4072,38 @@ var AgentFuel = class {
3387
4072
  throw mapSpendError(err, { service, amountUsdc, vault, policy });
3388
4073
  }
3389
4074
  }
4075
+ /// Atomic spend + record_payment in one transaction. Use this instead
4076
+ /// of `spend()` + `recordPayment()` when you want the vault burn and
4077
+ /// the reputation accrual to be all-or-nothing. The service keypair
4078
+ /// co-signs.
4079
+ async pay(args) {
4080
+ return pay({
4081
+ agent: this.agent,
4082
+ owner: this.resolveOwner(args.owner),
4083
+ service: args.service,
4084
+ amountUsdc: args.amountUsdc,
4085
+ receiptHash: args.receiptHash,
4086
+ connection: this.connection
4087
+ });
4088
+ }
4089
+ /// Submit an over-limit spend request the owner can approve from the
4090
+ /// mobile app. Returns the `pendingSpend` PDA so the bot can poll for
4091
+ /// resolution.
4092
+ async requestSpend(args) {
4093
+ return requestSpend({
4094
+ agent: this.agent,
4095
+ owner: this.resolveOwner(args.owner),
4096
+ service: args.service,
4097
+ amountUsdc: args.amountUsdc,
4098
+ connection: this.connection
4099
+ });
4100
+ }
4101
+ /// Register a service on chain. The `sponsor` (typically `this.agent`'s
4102
+ /// owner wallet) pays rent; the `service` keypair is the long-lived
4103
+ /// identity that will co-sign every future `record_payment`.
4104
+ async registerService(args) {
4105
+ return registerService({ ...args, connection: this.connection });
4106
+ }
3390
4107
  /// Triggers an on-chain recomputation of the agent's reputation score.
3391
4108
  /// Permissionless — any signer can call it; we use the agent itself since
3392
4109
  /// the SDK already has its keypair available and it already pays tx fees
@@ -3606,10 +4323,14 @@ exports.agentProfilePda = agentProfilePda;
3606
4323
  exports.agentServiceLinkPda = agentServiceLinkPda;
3607
4324
  exports.createAssociatedTokenAccountIdempotentInstruction = createAssociatedTokenAccountIdempotentInstruction;
3608
4325
  exports.getAssociatedTokenAddress = getAssociatedTokenAddress;
4326
+ exports.pay = pay;
3609
4327
  exports.paymentRequired = paymentRequired;
4328
+ exports.pendingSpendPda = pendingSpendPda;
3610
4329
  exports.policyPda = policyPda;
3611
4330
  exports.receiptUsedPda = receiptUsedPda;
3612
4331
  exports.recordPayment = recordPayment;
4332
+ exports.registerService = registerService;
4333
+ exports.requestSpend = requestSpend;
3613
4334
  exports.serviceRegistryPda = serviceRegistryPda;
3614
4335
  exports.subscribeService = subscribeService;
3615
4336
  exports.subscribeVault = subscribeVault;