@agent-fuel/sdk 0.1.0 → 0.2.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.js CHANGED
@@ -1,5 +1,5 @@
1
- import { BN, AnchorError, Program, AnchorProvider, Wallet } from '@coral-xyz/anchor';
2
- import { PublicKey, TransactionInstruction, SystemProgram, Connection } from '@solana/web3.js';
1
+ import { BN, AnchorError, AnchorProvider, Wallet, Program } from '@coral-xyz/anchor';
2
+ import { PublicKey, TransactionInstruction, SystemProgram, Transaction, sendAndConfirmTransaction, Connection } from '@solana/web3.js';
3
3
 
4
4
  // src/client.ts
5
5
  var TOKEN_PROGRAM_ID = new PublicKey("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA");
@@ -61,7 +61,8 @@ function decodeCreditVault(pubkey, raw) {
61
61
  balance: total_deposited - total_withdrawn - total_spent + total_claimed,
62
62
  frozen: raw.frozen,
63
63
  created_slot: bnToNum(raw.createdSlot),
64
- last_active_slot: bnToNum(raw.lastActiveSlot)
64
+ last_active_slot: bnToNum(raw.lastActiveSlot),
65
+ pending_count: bnToNum(raw.pendingCount)
65
66
  };
66
67
  }
67
68
  var DEFAULT_PUBKEY = PublicKey.default.toBase58();
@@ -185,6 +186,28 @@ var NotWhitelistedError = class extends SpendPolicyError {
185
186
  this.service = service;
186
187
  }
187
188
  };
189
+ var RecordPaymentError = class extends AgentFuelError {
190
+ constructor(message) {
191
+ super(message);
192
+ this.name = "RecordPaymentError";
193
+ }
194
+ };
195
+ var ReceiptAlreadyRecordedError = class extends RecordPaymentError {
196
+ receiptHash;
197
+ constructor(receiptHash) {
198
+ super("payment receipt was already recorded on chain");
199
+ this.name = "ReceiptAlreadyRecordedError";
200
+ this.receiptHash = receiptHash;
201
+ }
202
+ };
203
+ var ServiceInactiveError = class extends RecordPaymentError {
204
+ service;
205
+ constructor(service) {
206
+ super(`service ${service} is paused; record_payment rejected`);
207
+ this.name = "ServiceInactiveError";
208
+ this.service = service;
209
+ }
210
+ };
188
211
 
189
212
  // src/guardrails.ts
190
213
  function guardSpend(args) {
@@ -292,6 +315,12 @@ function wsUrl(apiBase, path) {
292
315
  if (apiBase.startsWith("http://")) return apiBase.replace(/^http/, "ws") + path;
293
316
  return apiBase + path;
294
317
  }
318
+ function subscribeService(apiBase, servicePubkey, opts) {
319
+ return subscribe(wsUrl(apiBase, `/ws/services/${servicePubkey}`), opts);
320
+ }
321
+ function subscribeVault(apiBase, vaultPubkey, opts) {
322
+ return subscribe(wsUrl(apiBase, `/ws/vaults/${vaultPubkey}`), opts);
323
+ }
295
324
 
296
325
  // src/idl/reputation.json
297
326
  var reputation_default = {
@@ -847,10 +876,14 @@ var reputation_default = {
847
876
  ],
848
877
  accounts: [
849
878
  {
850
- name: "service",
879
+ name: "sponsor",
851
880
  writable: true,
852
881
  signer: true
853
882
  },
883
+ {
884
+ name: "service",
885
+ signer: true
886
+ },
854
887
  {
855
888
  name: "service_registry",
856
889
  writable: true,
@@ -897,6 +930,15 @@ var reputation_default = {
897
930
  name: "ServiceCategory"
898
931
  }
899
932
  }
933
+ },
934
+ {
935
+ name: "service_uri",
936
+ type: {
937
+ array: [
938
+ "u8",
939
+ 128
940
+ ]
941
+ }
900
942
  }
901
943
  ]
902
944
  },
@@ -1012,6 +1054,61 @@ var reputation_default = {
1012
1054
  }
1013
1055
  }
1014
1056
  ]
1057
+ },
1058
+ {
1059
+ name: "set_service_active",
1060
+ discriminator: [
1061
+ 221,
1062
+ 172,
1063
+ 149,
1064
+ 49,
1065
+ 212,
1066
+ 184,
1067
+ 77,
1068
+ 101
1069
+ ],
1070
+ accounts: [
1071
+ {
1072
+ name: "service",
1073
+ signer: true
1074
+ },
1075
+ {
1076
+ name: "service_registry",
1077
+ writable: true,
1078
+ pda: {
1079
+ seeds: [
1080
+ {
1081
+ kind: "const",
1082
+ value: [
1083
+ 115,
1084
+ 101,
1085
+ 114,
1086
+ 118,
1087
+ 105,
1088
+ 99,
1089
+ 101
1090
+ ]
1091
+ },
1092
+ {
1093
+ kind: "account",
1094
+ path: "service"
1095
+ }
1096
+ ]
1097
+ }
1098
+ },
1099
+ {
1100
+ name: "authority",
1101
+ relations: [
1102
+ "service_registry"
1103
+ ]
1104
+ }
1105
+ ],
1106
+ args: [
1107
+ {
1108
+ name: "active",
1109
+ type: "bool"
1110
+ }
1111
+ ]
1015
1112
  }
1016
1113
  ],
1017
1114
  accounts: [
@@ -1160,6 +1257,19 @@ var reputation_default = {
1160
1257
  109
1161
1258
  ]
1162
1259
  },
1260
+ {
1261
+ name: "ServiceActiveSet",
1262
+ discriminator: [
1263
+ 151,
1264
+ 122,
1265
+ 7,
1266
+ 40,
1267
+ 191,
1268
+ 139,
1269
+ 237,
1270
+ 52
1271
+ ]
1272
+ },
1163
1273
  {
1164
1274
  name: "ServiceRegistered",
1165
1275
  discriminator: [
@@ -1224,6 +1334,11 @@ var reputation_default = {
1224
1334
  code: 6009,
1225
1335
  name: "FeedbackRateLimited",
1226
1336
  msg: "Feedback rate limit not yet expired for this (service, agent) pair"
1337
+ },
1338
+ {
1339
+ code: 6010,
1340
+ name: "UnauthorizedService",
1341
+ msg: "Only the service authority may perform this action"
1227
1342
  }
1228
1343
  ],
1229
1344
  types: [
@@ -1664,6 +1779,26 @@ var reputation_default = {
1664
1779
  ]
1665
1780
  }
1666
1781
  },
1782
+ {
1783
+ name: "ServiceActiveSet",
1784
+ type: {
1785
+ kind: "struct",
1786
+ fields: [
1787
+ {
1788
+ name: "service",
1789
+ type: "pubkey"
1790
+ },
1791
+ {
1792
+ name: "active",
1793
+ type: "bool"
1794
+ },
1795
+ {
1796
+ name: "slot",
1797
+ type: "u64"
1798
+ }
1799
+ ]
1800
+ }
1801
+ },
1667
1802
  {
1668
1803
  name: "ServiceCategory",
1669
1804
  type: {
@@ -1696,6 +1831,14 @@ var reputation_default = {
1696
1831
  name: "service",
1697
1832
  type: "pubkey"
1698
1833
  },
1834
+ {
1835
+ name: "sponsor",
1836
+ docs: [
1837
+ 'Wallet that paid rent. Lets us answer "who registered this service?"',
1838
+ "without an extra column on the on-chain account."
1839
+ ],
1840
+ type: "pubkey"
1841
+ },
1699
1842
  {
1700
1843
  name: "name",
1701
1844
  type: {
@@ -1738,6 +1881,19 @@ var reputation_default = {
1738
1881
  ]
1739
1882
  }
1740
1883
  },
1884
+ {
1885
+ name: "service_uri",
1886
+ docs: [
1887
+ "Off-chain metadata URI (pricing, docs, endpoint, logo). Padded to 128 bytes;",
1888
+ "trailing NULs are trimmed when read. Mirrors `AgentProfile::agent_uri`."
1889
+ ],
1890
+ type: {
1891
+ array: [
1892
+ "u8",
1893
+ 128
1894
+ ]
1895
+ }
1896
+ },
1741
1897
  {
1742
1898
  name: "category",
1743
1899
  type: {
@@ -1797,21 +1953,25 @@ var credit_vault_default = {
1797
1953
  },
1798
1954
  instructions: [
1799
1955
  {
1800
- name: "claim",
1956
+ name: "approve_spend",
1801
1957
  discriminator: [
1802
- 62,
1803
- 198,
1804
- 214,
1805
- 193,
1806
- 213,
1807
- 159,
1808
- 108,
1809
- 210
1958
+ 248,
1959
+ 201,
1960
+ 151,
1961
+ 15,
1962
+ 28,
1963
+ 162,
1964
+ 112,
1965
+ 90
1810
1966
  ],
1811
1967
  accounts: [
1812
1968
  {
1813
- name: "service",
1814
- signer: true
1969
+ name: "owner",
1970
+ writable: true,
1971
+ signer: true,
1972
+ relations: [
1973
+ "vault"
1974
+ ]
1815
1975
  },
1816
1976
  {
1817
1977
  name: "vault",
@@ -1830,8 +1990,7 @@ var credit_vault_default = {
1830
1990
  },
1831
1991
  {
1832
1992
  kind: "account",
1833
- path: "vault.owner",
1834
- account: "CreditVault"
1993
+ path: "owner"
1835
1994
  },
1836
1995
  {
1837
1996
  kind: "account",
@@ -1864,6 +2023,35 @@ var credit_vault_default = {
1864
2023
  ]
1865
2024
  }
1866
2025
  },
2026
+ {
2027
+ name: "pending_spend",
2028
+ writable: true,
2029
+ pda: {
2030
+ seeds: [
2031
+ {
2032
+ kind: "const",
2033
+ value: [
2034
+ 112,
2035
+ 101,
2036
+ 110,
2037
+ 100,
2038
+ 105,
2039
+ 110,
2040
+ 103
2041
+ ]
2042
+ },
2043
+ {
2044
+ kind: "account",
2045
+ path: "vault"
2046
+ },
2047
+ {
2048
+ kind: "account",
2049
+ path: "pending_spend.nonce",
2050
+ account: "PendingSpend"
2051
+ }
2052
+ ]
2053
+ }
2054
+ },
1867
2055
  {
1868
2056
  name: "vault_token_account",
1869
2057
  writable: true
@@ -1877,43 +2065,31 @@ var credit_vault_default = {
1877
2065
  address: "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
1878
2066
  }
1879
2067
  ],
1880
- args: [
1881
- {
1882
- name: "amount_usdc",
1883
- type: "u64"
1884
- }
1885
- ]
2068
+ args: []
1886
2069
  },
1887
2070
  {
1888
- name: "create_vault",
2071
+ name: "cancel_spend",
1889
2072
  discriminator: [
1890
- 29,
1891
- 237,
1892
- 247,
1893
- 208,
1894
- 193,
1895
- 82,
1896
- 54,
1897
- 135
2073
+ 122,
2074
+ 254,
2075
+ 101,
2076
+ 132,
2077
+ 241,
2078
+ 232,
2079
+ 205,
2080
+ 179
1898
2081
  ],
1899
2082
  accounts: [
1900
2083
  {
1901
2084
  name: "owner",
1902
2085
  writable: true,
1903
- signer: true
1904
- },
1905
- {
1906
- name: "agent",
1907
- docs: [
1908
- "account need not exist on chain; we never read or write its data."
2086
+ signer: true,
2087
+ relations: [
2088
+ "vault"
1909
2089
  ]
1910
2090
  },
1911
- {
1912
- name: "usdc_mint"
1913
- },
1914
2091
  {
1915
2092
  name: "vault",
1916
- writable: true,
1917
2093
  pda: {
1918
2094
  seeds: [
1919
2095
  {
@@ -1932,13 +2108,14 @@ var credit_vault_default = {
1932
2108
  },
1933
2109
  {
1934
2110
  kind: "account",
1935
- path: "agent"
2111
+ path: "vault.agent",
2112
+ account: "CreditVault"
1936
2113
  }
1937
2114
  ]
1938
2115
  }
1939
2116
  },
1940
2117
  {
1941
- name: "policy",
2118
+ name: "pending_spend",
1942
2119
  writable: true,
1943
2120
  pda: {
1944
2121
  seeds: [
@@ -1946,38 +2123,211 @@ var credit_vault_default = {
1946
2123
  kind: "const",
1947
2124
  value: [
1948
2125
  112,
1949
- 111,
1950
- 108,
2126
+ 101,
2127
+ 110,
2128
+ 100,
1951
2129
  105,
1952
- 99,
1953
- 121
2130
+ 110,
2131
+ 103
1954
2132
  ]
1955
2133
  },
1956
2134
  {
1957
2135
  kind: "account",
1958
2136
  path: "vault"
2137
+ },
2138
+ {
2139
+ kind: "account",
2140
+ path: "pending_spend.nonce",
2141
+ account: "PendingSpend"
1959
2142
  }
1960
2143
  ]
1961
2144
  }
2145
+ }
2146
+ ],
2147
+ args: []
2148
+ },
2149
+ {
2150
+ name: "claim",
2151
+ discriminator: [
2152
+ 62,
2153
+ 198,
2154
+ 214,
2155
+ 193,
2156
+ 213,
2157
+ 159,
2158
+ 108,
2159
+ 210
2160
+ ],
2161
+ accounts: [
2162
+ {
2163
+ name: "service",
2164
+ signer: true
1962
2165
  },
1963
2166
  {
1964
- name: "vault_token_account",
2167
+ name: "vault",
1965
2168
  writable: true,
1966
2169
  pda: {
1967
2170
  seeds: [
2171
+ {
2172
+ kind: "const",
2173
+ value: [
2174
+ 118,
2175
+ 97,
2176
+ 117,
2177
+ 108,
2178
+ 116
2179
+ ]
2180
+ },
1968
2181
  {
1969
2182
  kind: "account",
1970
- path: "vault"
2183
+ path: "vault.owner",
2184
+ account: "CreditVault"
1971
2185
  },
1972
2186
  {
1973
- kind: "const",
1974
- value: [
1975
- 6,
1976
- 221,
1977
- 246,
1978
- 225,
1979
- 215,
1980
- 101,
2187
+ kind: "account",
2188
+ path: "vault.agent",
2189
+ account: "CreditVault"
2190
+ }
2191
+ ]
2192
+ }
2193
+ },
2194
+ {
2195
+ name: "policy",
2196
+ writable: true,
2197
+ pda: {
2198
+ seeds: [
2199
+ {
2200
+ kind: "const",
2201
+ value: [
2202
+ 112,
2203
+ 111,
2204
+ 108,
2205
+ 105,
2206
+ 99,
2207
+ 121
2208
+ ]
2209
+ },
2210
+ {
2211
+ kind: "account",
2212
+ path: "vault"
2213
+ }
2214
+ ]
2215
+ }
2216
+ },
2217
+ {
2218
+ name: "vault_token_account",
2219
+ writable: true
2220
+ },
2221
+ {
2222
+ name: "service_token_account",
2223
+ writable: true
2224
+ },
2225
+ {
2226
+ name: "token_program",
2227
+ address: "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
2228
+ }
2229
+ ],
2230
+ args: [
2231
+ {
2232
+ name: "amount_usdc",
2233
+ type: "u64"
2234
+ }
2235
+ ]
2236
+ },
2237
+ {
2238
+ name: "create_vault",
2239
+ discriminator: [
2240
+ 29,
2241
+ 237,
2242
+ 247,
2243
+ 208,
2244
+ 193,
2245
+ 82,
2246
+ 54,
2247
+ 135
2248
+ ],
2249
+ accounts: [
2250
+ {
2251
+ name: "owner",
2252
+ writable: true,
2253
+ signer: true
2254
+ },
2255
+ {
2256
+ name: "agent",
2257
+ docs: [
2258
+ "account need not exist on chain; we never read or write its data."
2259
+ ]
2260
+ },
2261
+ {
2262
+ name: "usdc_mint"
2263
+ },
2264
+ {
2265
+ name: "vault",
2266
+ writable: true,
2267
+ pda: {
2268
+ seeds: [
2269
+ {
2270
+ kind: "const",
2271
+ value: [
2272
+ 118,
2273
+ 97,
2274
+ 117,
2275
+ 108,
2276
+ 116
2277
+ ]
2278
+ },
2279
+ {
2280
+ kind: "account",
2281
+ path: "owner"
2282
+ },
2283
+ {
2284
+ kind: "account",
2285
+ path: "agent"
2286
+ }
2287
+ ]
2288
+ }
2289
+ },
2290
+ {
2291
+ name: "policy",
2292
+ writable: true,
2293
+ pda: {
2294
+ seeds: [
2295
+ {
2296
+ kind: "const",
2297
+ value: [
2298
+ 112,
2299
+ 111,
2300
+ 108,
2301
+ 105,
2302
+ 99,
2303
+ 121
2304
+ ]
2305
+ },
2306
+ {
2307
+ kind: "account",
2308
+ path: "vault"
2309
+ }
2310
+ ]
2311
+ }
2312
+ },
2313
+ {
2314
+ name: "vault_token_account",
2315
+ writable: true,
2316
+ pda: {
2317
+ seeds: [
2318
+ {
2319
+ kind: "account",
2320
+ path: "vault"
2321
+ },
2322
+ {
2323
+ kind: "const",
2324
+ value: [
2325
+ 6,
2326
+ 221,
2327
+ 246,
2328
+ 225,
2329
+ 215,
2330
+ 101,
1981
2331
  161,
1982
2332
  147,
1983
2333
  217,
@@ -2202,6 +2552,104 @@ var credit_vault_default = {
2202
2552
  ],
2203
2553
  args: []
2204
2554
  },
2555
+ {
2556
+ name: "request_spend",
2557
+ discriminator: [
2558
+ 127,
2559
+ 12,
2560
+ 23,
2561
+ 75,
2562
+ 137,
2563
+ 178,
2564
+ 148,
2565
+ 71
2566
+ ],
2567
+ accounts: [
2568
+ {
2569
+ name: "agent",
2570
+ writable: true,
2571
+ signer: true,
2572
+ relations: [
2573
+ "vault"
2574
+ ]
2575
+ },
2576
+ {
2577
+ name: "vault",
2578
+ writable: true,
2579
+ pda: {
2580
+ seeds: [
2581
+ {
2582
+ kind: "const",
2583
+ value: [
2584
+ 118,
2585
+ 97,
2586
+ 117,
2587
+ 108,
2588
+ 116
2589
+ ]
2590
+ },
2591
+ {
2592
+ kind: "account",
2593
+ path: "vault.owner",
2594
+ account: "CreditVault"
2595
+ },
2596
+ {
2597
+ kind: "account",
2598
+ path: "vault.agent",
2599
+ account: "CreditVault"
2600
+ }
2601
+ ]
2602
+ }
2603
+ },
2604
+ {
2605
+ name: "service_token_account",
2606
+ docs: [
2607
+ "The recipient token account. We only need it for its `owner` field",
2608
+ "(the service pubkey we record in PendingSpend); mint constraint is",
2609
+ "belt-and-suspenders since `approve_spend` re-checks both."
2610
+ ]
2611
+ },
2612
+ {
2613
+ name: "pending_spend",
2614
+ writable: true,
2615
+ pda: {
2616
+ seeds: [
2617
+ {
2618
+ kind: "const",
2619
+ value: [
2620
+ 112,
2621
+ 101,
2622
+ 110,
2623
+ 100,
2624
+ 105,
2625
+ 110,
2626
+ 103
2627
+ ]
2628
+ },
2629
+ {
2630
+ kind: "account",
2631
+ path: "vault"
2632
+ },
2633
+ {
2634
+ kind: "account",
2635
+ path: "vault.pending_count",
2636
+ account: "CreditVault"
2637
+ }
2638
+ ]
2639
+ }
2640
+ },
2641
+ {
2642
+ name: "system_program",
2643
+ address: "11111111111111111111111111111111"
2644
+ }
2645
+ ],
2646
+ args: [
2647
+ {
2648
+ name: "amount_usdc",
2649
+ type: "u64"
2650
+ }
2651
+ ]
2652
+ },
2205
2653
  {
2206
2654
  name: "spend",
2207
2655
  discriminator: [
@@ -2527,6 +2975,19 @@ var credit_vault_default = {
2527
2975
  70
2528
2976
  ]
2529
2977
  },
2978
+ {
2979
+ name: "PendingSpend",
2980
+ discriminator: [
2981
+ 193,
2982
+ 205,
2983
+ 85,
2984
+ 66,
2985
+ 25,
2986
+ 3,
2987
+ 67,
2988
+ 134
2989
+ ]
2990
+ },
2530
2991
  {
2531
2992
  name: "SpendPolicy",
2532
2993
  discriminator: [
@@ -2581,6 +3042,32 @@ var credit_vault_default = {
2581
3042
  161
2582
3043
  ]
2583
3044
  },
3045
+ {
3046
+ name: "SpendRejected",
3047
+ discriminator: [
3048
+ 22,
3049
+ 233,
3050
+ 208,
3051
+ 109,
3052
+ 202,
3053
+ 231,
3054
+ 175,
3055
+ 22
3056
+ ]
3057
+ },
3058
+ {
3059
+ name: "SpendRequested",
3060
+ discriminator: [
3061
+ 144,
3062
+ 207,
3063
+ 254,
3064
+ 247,
3065
+ 81,
3066
+ 146,
3067
+ 84,
3068
+ 87
3069
+ ]
3070
+ },
2584
3071
  {
2585
3072
  name: "Spent",
2586
3073
  discriminator: [
@@ -2697,6 +3184,16 @@ var credit_vault_default = {
2697
3184
  code: 6009,
2698
3185
  name: "PostPayDisabled",
2699
3186
  msg: "Post-pay claims are disabled for this vault"
3187
+ },
3188
+ {
3189
+ code: 6010,
3190
+ name: "PendingSpendVaultMismatch",
3191
+ msg: "Pending spend belongs to a different vault"
3192
+ },
3193
+ {
3194
+ code: 6011,
3195
+ name: "PendingNonceOverflow",
3196
+ msg: "Pending spend counter would overflow"
2700
3197
  }
2701
3198
  ],
2702
3199
  types: [
@@ -2785,12 +3282,22 @@ var credit_vault_default = {
2785
3282
  name: "bump",
2786
3283
  type: "u8"
2787
3284
  },
3285
+ {
3286
+ name: "pending_count",
3287
+ docs: [
3288
+ "Monotonic counter used as a PDA seed for PendingSpend accounts so",
3289
+ "every approval request gets a unique deterministic address.",
3290
+ "Borrowed 8 bytes from the original 64-byte padding so the account",
3291
+ "size stays at `ACCOUNT_SIZE` and existing vaults need no migration."
3292
+ ],
3293
+ type: "u64"
3294
+ },
2788
3295
  {
2789
3296
  name: "_padding",
2790
3297
  type: {
2791
3298
  array: [
2792
3299
  "u8",
2793
- 64
3300
+ 56
2794
3301
  ]
2795
3302
  }
2796
3303
  }
@@ -2825,6 +3332,65 @@ var credit_vault_default = {
2825
3332
  ]
2826
3333
  }
2827
3334
  },
3335
+ {
3336
+ name: "PendingSpend",
3337
+ docs: [
3338
+ "A spend request that exceeded one of the policy's rate limits. The agent",
3339
+ "creates this account by calling `request_spend`; the owner reviews from",
3340
+ "the mobile Alerts tab and either calls `approve_spend` (PDA-signed CPI",
3341
+ "transfer, account closed) or `cancel_spend` (account closed, no transfer).",
3342
+ "",
3343
+ 'Seeded by `["pending", vault, nonce_le]` where `nonce` is the value of',
3344
+ "`vault.pending_count` at request time, so each request has a unique",
3345
+ "deterministic address that both the agent and the owner can derive."
3346
+ ],
3347
+ type: {
3348
+ kind: "struct",
3349
+ fields: [
3350
+ {
3351
+ name: "vault",
3352
+ type: "pubkey"
3353
+ },
3354
+ {
3355
+ name: "agent",
3356
+ type: "pubkey"
3357
+ },
3358
+ {
3359
+ name: "service",
3360
+ docs: [
3361
+ "Owner of the destination token account (mirrors how `Spent` records",
3362
+ "service: `service_token_account.owner`)."
3363
+ ],
3364
+ type: "pubkey"
3365
+ },
3366
+ {
3367
+ name: "amount_usdc",
3368
+ type: "u64"
3369
+ },
3370
+ {
3371
+ name: "requested_slot",
3372
+ type: "u64"
3373
+ },
3374
+ {
3375
+ name: "nonce",
3376
+ type: "u64"
3377
+ },
3378
+ {
3379
+ name: "bump",
3380
+ type: "u8"
3381
+ },
3382
+ {
3383
+ name: "_padding",
3384
+ type: {
3385
+ array: [
3386
+ "u8",
3387
+ 31
3388
+ ]
3389
+ }
3390
+ }
3391
+ ]
3392
+ }
3393
+ },
2828
3394
  {
2829
3395
  name: "PolicyUpdated",
2830
3396
  type: {
@@ -2928,6 +3494,70 @@ var credit_vault_default = {
2928
3494
  ]
2929
3495
  }
2930
3496
  },
3497
+ {
3498
+ name: "SpendRejected",
3499
+ type: {
3500
+ kind: "struct",
3501
+ fields: [
3502
+ {
3503
+ name: "vault",
3504
+ type: "pubkey"
3505
+ },
3506
+ {
3507
+ name: "owner",
3508
+ type: "pubkey"
3509
+ },
3510
+ {
3511
+ name: "pending_spend",
3512
+ type: "pubkey"
3513
+ },
3514
+ {
3515
+ name: "nonce",
3516
+ type: "u64"
3517
+ },
3518
+ {
3519
+ name: "slot",
3520
+ type: "u64"
3521
+ }
3522
+ ]
3523
+ }
3524
+ },
3525
+ {
3526
+ name: "SpendRequested",
3527
+ type: {
3528
+ kind: "struct",
3529
+ fields: [
3530
+ {
3531
+ name: "vault",
3532
+ type: "pubkey"
3533
+ },
3534
+ {
3535
+ name: "agent",
3536
+ type: "pubkey"
3537
+ },
3538
+ {
3539
+ name: "service",
3540
+ type: "pubkey"
3541
+ },
3542
+ {
3543
+ name: "pending_spend",
3544
+ type: "pubkey"
3545
+ },
3546
+ {
3547
+ name: "amount_usdc",
3548
+ type: "u64"
3549
+ },
3550
+ {
3551
+ name: "nonce",
3552
+ type: "u64"
3553
+ },
3554
+ {
3555
+ name: "slot",
3556
+ type: "u64"
3557
+ }
3558
+ ]
3559
+ }
3560
+ },
2931
3561
  {
2932
3562
  name: "Spent",
2933
3563
  type: {
@@ -3094,6 +3724,43 @@ function serviceRegistryPda(serviceAuthority) {
3094
3724
  );
3095
3725
  return pda;
3096
3726
  }
3727
+ function agentProfilePda(agent) {
3728
+ const [pda] = PublicKey.findProgramAddressSync(
3729
+ [Buffer.from("agent"), toPubkey(agent).toBuffer()],
3730
+ PROGRAM_IDS.reputation
3731
+ );
3732
+ return pda;
3733
+ }
3734
+ function agentServiceLinkPda(agentProfile, serviceRegistry) {
3735
+ const [pda] = PublicKey.findProgramAddressSync(
3736
+ [
3737
+ Buffer.from("link"),
3738
+ toPubkey(agentProfile).toBuffer(),
3739
+ toPubkey(serviceRegistry).toBuffer()
3740
+ ],
3741
+ PROGRAM_IDS.reputation
3742
+ );
3743
+ return pda;
3744
+ }
3745
+ function pendingSpendPda(vault, nonce) {
3746
+ const nonceBuf = Buffer.alloc(8);
3747
+ nonceBuf.writeBigUInt64LE(typeof nonce === "bigint" ? nonce : BigInt(nonce));
3748
+ const [pda] = PublicKey.findProgramAddressSync(
3749
+ [Buffer.from("pending"), toPubkey(vault).toBuffer(), nonceBuf],
3750
+ PROGRAM_IDS.creditVault
3751
+ );
3752
+ return pda;
3753
+ }
3754
+ function receiptUsedPda(receiptHash) {
3755
+ if (receiptHash.length !== 32) {
3756
+ throw new Error(`receiptUsedPda expects a 32-byte hash, got ${receiptHash.length}`);
3757
+ }
3758
+ const [pda] = PublicKey.findProgramAddressSync(
3759
+ [Buffer.from("receipt"), Buffer.from(receiptHash)],
3760
+ PROGRAM_IDS.reputation
3761
+ );
3762
+ return pda;
3763
+ }
3097
3764
  function buildProvider(connection, keypair) {
3098
3765
  return new AnchorProvider(connection, new Wallet(keypair), AnchorProvider.defaultOptions());
3099
3766
  }
@@ -3104,6 +3771,207 @@ function reputationProgram(provider) {
3104
3771
  return new Program(reputation_default, provider);
3105
3772
  }
3106
3773
 
3774
+ // src/pay.ts
3775
+ async function pay(args) {
3776
+ const { agent, service, connection, amountUsdc } = args;
3777
+ const owner = toPubkey(args.owner);
3778
+ if (amountUsdc <= 0) {
3779
+ throw new ZeroAmountError();
3780
+ }
3781
+ if (args.receiptHash.length !== 32) {
3782
+ throw new Error(
3783
+ `pay: receiptHash must be 32 bytes, got ${args.receiptHash.length}`
3784
+ );
3785
+ }
3786
+ const vaultAddr = vaultPda(owner, agent.publicKey);
3787
+ const policyAddr = policyPda(vaultAddr);
3788
+ const provider = buildProvider(connection, agent);
3789
+ const cv = creditVaultProgram(provider);
3790
+ const rep = reputationProgram(provider);
3791
+ const [rawVault, rawPolicy, currentSlot] = await Promise.all([
3792
+ cv.account.creditVault.fetchNullable(vaultAddr),
3793
+ cv.account.spendPolicy.fetchNullable(policyAddr),
3794
+ connection.getSlot()
3795
+ ]);
3796
+ if (!rawVault) throw new AccountNotFoundError(vaultAddr.toBase58());
3797
+ if (!rawPolicy) throw new AccountNotFoundError(policyAddr.toBase58());
3798
+ const vault = decodeCreditVault(vaultAddr, rawVault);
3799
+ const policy = decodeSpendPolicy(policyAddr, rawPolicy);
3800
+ guardSpend({
3801
+ vault,
3802
+ policy,
3803
+ service: service.publicKey,
3804
+ amountUsdc,
3805
+ currentSlot
3806
+ });
3807
+ const serviceTokenAccount = getAssociatedTokenAddress(
3808
+ vault.usdc_mint,
3809
+ service.publicKey
3810
+ );
3811
+ const createAtaIx = createAssociatedTokenAccountIdempotentInstruction(
3812
+ agent.publicKey,
3813
+ serviceTokenAccount,
3814
+ service.publicKey,
3815
+ vault.usdc_mint
3816
+ );
3817
+ const agentProfile = agentProfilePda(agent.publicKey);
3818
+ const serviceRegistry = serviceRegistryPda(service.publicKey);
3819
+ const link = agentServiceLinkPda(agentProfile, serviceRegistry);
3820
+ const receipt = receiptUsedPda(args.receiptHash);
3821
+ const spendBuilder = cv.methods.spend(new BN(amountUsdc)).accounts({
3822
+ agent: agent.publicKey,
3823
+ vault: vaultAddr,
3824
+ policy: policyAddr,
3825
+ vaultTokenAccount: vault.vault_token_account,
3826
+ serviceTokenAccount,
3827
+ tokenProgram: TOKEN_PROGRAM_ID
3828
+ });
3829
+ const recordBuilder = rep.methods.recordPayment(new BN(amountUsdc), args.receiptHash).accounts({
3830
+ service: service.publicKey,
3831
+ agentProfile,
3832
+ serviceRegistry,
3833
+ agentServiceLink: link,
3834
+ receiptUsed: receipt,
3835
+ systemProgram: SystemProgram.programId
3836
+ });
3837
+ const spendIx = await spendBuilder.instruction();
3838
+ const recordIx = await recordBuilder.instruction();
3839
+ const tx = new Transaction().add(createAtaIx, spendIx, recordIx);
3840
+ try {
3841
+ const signature = await sendAndConfirmTransaction(
3842
+ connection,
3843
+ tx,
3844
+ [agent, service],
3845
+ { commitment: "confirmed" }
3846
+ );
3847
+ return { signature };
3848
+ } catch (err) {
3849
+ throw mapPayError(err, {
3850
+ service: service.publicKey,
3851
+ amountUsdc,
3852
+ vault,
3853
+ policy,
3854
+ receiptHash: args.receiptHash
3855
+ });
3856
+ }
3857
+ }
3858
+ function mapPayError(err, ctx) {
3859
+ const message = err instanceof Error ? err.message : String(err);
3860
+ if (/already in use/i.test(message)) {
3861
+ return new ReceiptAlreadyRecordedError(ctx.receiptHash);
3862
+ }
3863
+ if (!(err instanceof AnchorError)) return err;
3864
+ switch (err.error.errorCode.number) {
3865
+ case 6001:
3866
+ return new ZeroAmountError();
3867
+ case 6002:
3868
+ return new VaultFrozenError();
3869
+ case 6003:
3870
+ return new NotWhitelistedError(ctx.service.toBase58());
3871
+ case 6004:
3872
+ return new PerTxLimitExceededError(ctx.amountUsdc, ctx.policy.per_tx_limit_usdc);
3873
+ case 6005:
3874
+ return new HourlyLimitExceededError(
3875
+ ctx.amountUsdc,
3876
+ ctx.policy.hourly_window_spent_usdc,
3877
+ ctx.policy.hourly_limit_usdc
3878
+ );
3879
+ case 6006:
3880
+ return new LifetimeLimitExceededError(
3881
+ ctx.amountUsdc,
3882
+ ctx.vault.total_spent,
3883
+ ctx.policy.lifetime_limit_usdc
3884
+ );
3885
+ // Reputation errors:
3886
+ case 6e3:
3887
+ return new RecordPaymentError("counter overflow on chain");
3888
+ case 6011:
3889
+ return new ServiceInactiveError(ctx.service.toBase58());
3890
+ default:
3891
+ return err;
3892
+ }
3893
+ }
3894
+ async function requestSpend(args) {
3895
+ const { agent, connection, amountUsdc } = args;
3896
+ const owner = toPubkey(args.owner);
3897
+ const service = toPubkey(args.service);
3898
+ if (amountUsdc <= 0) {
3899
+ throw new Error("requestSpend: amountUsdc must be > 0");
3900
+ }
3901
+ const vaultAddr = vaultPda(owner, agent.publicKey);
3902
+ const provider = buildProvider(connection, agent);
3903
+ const cv = creditVaultProgram(provider);
3904
+ const rawVault = await cv.account.creditVault.fetchNullable(vaultAddr);
3905
+ if (!rawVault) throw new AccountNotFoundError(vaultAddr.toBase58());
3906
+ const vault = decodeCreditVault(vaultAddr, rawVault);
3907
+ const nonce = vault.pending_count;
3908
+ const pendingSpend = pendingSpendPda(vaultAddr, nonce);
3909
+ const serviceTokenAccount = getAssociatedTokenAddress(
3910
+ vault.usdc_mint,
3911
+ service
3912
+ );
3913
+ const signature = await cv.methods.requestSpend(new BN(amountUsdc)).accounts({
3914
+ agent: agent.publicKey,
3915
+ vault: vaultAddr,
3916
+ serviceTokenAccount,
3917
+ pendingSpend,
3918
+ systemProgram: SystemProgram.programId
3919
+ }).signers([agent]).rpc();
3920
+ return { signature, pendingSpend, nonce };
3921
+ }
3922
+ var NAME_BYTES = 32;
3923
+ var URI_BYTES = 128;
3924
+ async function registerService(args) {
3925
+ const { sponsor, service, connection } = args;
3926
+ if (args.name.length === 0) {
3927
+ throw new Error("registerService: name must not be empty");
3928
+ }
3929
+ if (Buffer.byteLength(args.name, "utf8") > NAME_BYTES) {
3930
+ throw new Error(
3931
+ `registerService: name exceeds ${NAME_BYTES} bytes (got ${Buffer.byteLength(args.name, "utf8")})`
3932
+ );
3933
+ }
3934
+ const uri = args.serviceUri ?? "";
3935
+ if (Buffer.byteLength(uri, "utf8") > URI_BYTES) {
3936
+ throw new Error(
3937
+ `registerService: serviceUri exceeds ${URI_BYTES} bytes (got ${Buffer.byteLength(uri, "utf8")})`
3938
+ );
3939
+ }
3940
+ const registry = serviceRegistryPda(service.publicKey);
3941
+ const provider = buildProvider(connection, sponsor);
3942
+ const rep = reputationProgram(provider);
3943
+ const signature = await rep.methods.registerService(
3944
+ packFixed(args.name, NAME_BYTES),
3945
+ categoryArg(args.category),
3946
+ packFixed(uri, URI_BYTES)
3947
+ ).accounts({
3948
+ sponsor: sponsor.publicKey,
3949
+ service: service.publicKey,
3950
+ serviceRegistry: registry,
3951
+ systemProgram: SystemProgram.programId
3952
+ }).signers([sponsor, service]).rpc();
3953
+ return { signature };
3954
+ }
3955
+ function packFixed(s, length) {
3956
+ const buf = Buffer.alloc(length);
3957
+ buf.write(s, 0, "utf8");
3958
+ return Array.from(buf);
3959
+ }
3960
+ function categoryArg(c) {
3961
+ switch (c) {
3962
+ case "DataFeed":
3963
+ return { dataFeed: {} };
3964
+ case "Compute":
3965
+ return { compute: {} };
3966
+ case "Swap":
3967
+ return { swap: {} };
3968
+ case "Rpc":
3969
+ return { rpc: {} };
3970
+ case "Other":
3971
+ return { other: {} };
3972
+ }
3973
+ }
3974
+
3107
3975
  // src/client.ts
3108
3976
  var DEFAULT_API_BASE = "http://localhost:8080";
3109
3977
  var AgentFuel = class {
@@ -3202,6 +4070,53 @@ var AgentFuel = class {
3202
4070
  throw mapSpendError(err, { service, amountUsdc, vault, policy });
3203
4071
  }
3204
4072
  }
4073
+ /// Atomic spend + record_payment in one transaction. Use this instead
4074
+ /// of `spend()` + `recordPayment()` when you want the vault burn and
4075
+ /// the reputation accrual to be all-or-nothing. The service keypair
4076
+ /// co-signs.
4077
+ async pay(args) {
4078
+ return pay({
4079
+ agent: this.agent,
4080
+ owner: this.resolveOwner(args.owner),
4081
+ service: args.service,
4082
+ amountUsdc: args.amountUsdc,
4083
+ receiptHash: args.receiptHash,
4084
+ connection: this.connection
4085
+ });
4086
+ }
4087
+ /// Submit an over-limit spend request the owner can approve from the
4088
+ /// mobile app. Returns the `pendingSpend` PDA so the bot can poll for
4089
+ /// resolution.
4090
+ async requestSpend(args) {
4091
+ return requestSpend({
4092
+ agent: this.agent,
4093
+ owner: this.resolveOwner(args.owner),
4094
+ service: args.service,
4095
+ amountUsdc: args.amountUsdc,
4096
+ connection: this.connection
4097
+ });
4098
+ }
4099
+ /// Register a service on chain. The `sponsor` (typically `this.agent`'s
4100
+ /// owner wallet) pays rent; the `service` keypair is the long-lived
4101
+ /// identity that will co-sign every future `record_payment`.
4102
+ async registerService(args) {
4103
+ return registerService({ ...args, connection: this.connection });
4104
+ }
4105
+ /// Triggers an on-chain recomputation of the agent's reputation score.
4106
+ /// Permissionless — any signer can call it; we use the agent itself since
4107
+ /// the SDK already has its keypair available and it already pays tx fees
4108
+ /// for spends. The instruction reads the agent's already-public counters
4109
+ /// (volume, diversity, streak, tenure, feedback), recalculates the score
4110
+ /// to a single u16 ≤ 1000, and emits a `ScoreComputed` event. The webhook
4111
+ /// picks that up; the next `getScore()` returns the fresh value.
4112
+ async computeScore() {
4113
+ const profile = agentProfilePda(this.agentPubkey);
4114
+ const signature = await this.reputation.methods.computeScore().accounts({
4115
+ caller: this.agentPubkey,
4116
+ agentProfile: profile
4117
+ }).signers([this.agent]).rpc();
4118
+ return { signature };
4119
+ }
3205
4120
  onEvent(callback, options) {
3206
4121
  const target = options?.agent ? toPubkey(options.agent) : this.agentPubkey;
3207
4122
  const url = wsUrl(this.apiBase, `/ws/agents/${target.toBase58()}`);
@@ -3246,6 +4161,56 @@ async function safeText(res) {
3246
4161
  return void 0;
3247
4162
  }
3248
4163
  }
4164
+ async function recordPayment(args) {
4165
+ const { service, connection, amountUsdc } = args;
4166
+ const agentPubkey = toPubkey(args.agent);
4167
+ if (amountUsdc <= 0) {
4168
+ throw new Error("recordPayment: amountUsdc must be > 0");
4169
+ }
4170
+ if (args.receiptHash.length !== 32) {
4171
+ throw new Error(
4172
+ `recordPayment: receiptHash must be 32 bytes, got ${args.receiptHash.length}`
4173
+ );
4174
+ }
4175
+ const provider = buildProvider(connection, service);
4176
+ const program = reputationProgram(provider);
4177
+ const agentProfile = agentProfilePda(agentPubkey);
4178
+ const serviceRegistry = serviceRegistryPda(service.publicKey);
4179
+ const link = agentServiceLinkPda(agentProfile, serviceRegistry);
4180
+ const receipt = receiptUsedPda(args.receiptHash);
4181
+ try {
4182
+ const signature = await program.methods.recordPayment(new BN(amountUsdc), args.receiptHash).accounts({
4183
+ service: service.publicKey,
4184
+ agentProfile,
4185
+ serviceRegistry,
4186
+ agentServiceLink: link,
4187
+ receiptUsed: receipt,
4188
+ systemProgram: SystemProgram.programId
4189
+ }).signers([service]).rpc();
4190
+ return { signature };
4191
+ } catch (err) {
4192
+ throw mapRecordPaymentError(err, args.receiptHash);
4193
+ }
4194
+ }
4195
+ function mapRecordPaymentError(err, receiptHash) {
4196
+ const message = err instanceof Error ? err.message : String(err);
4197
+ if (/already in use/i.test(message)) {
4198
+ return new ReceiptAlreadyRecordedError(receiptHash);
4199
+ }
4200
+ if (!(err instanceof AnchorError)) return err;
4201
+ switch (err.error.errorCode.number) {
4202
+ case 6e3:
4203
+ return new RecordPaymentError("counter overflow on chain");
4204
+ case 6001:
4205
+ return new ServiceInactiveError(
4206
+ err.error.origin?.toString() ?? "<unknown service>"
4207
+ );
4208
+ case 6002:
4209
+ return new ZeroAmountError();
4210
+ default:
4211
+ return err;
4212
+ }
4213
+ }
3249
4214
 
3250
4215
  // src/x402.ts
3251
4216
  var HEADER = "X-Payment-Required";
@@ -3332,6 +4297,6 @@ function truncate(s) {
3332
4297
  return s.length > 80 ? `${s.slice(0, 80)}\u2026` : s;
3333
4298
  }
3334
4299
 
3335
- export { ASSOCIATED_TOKEN_PROGRAM_ID, AccountNotFoundError, AgentFuel, AgentFuelError, HourlyLimitExceededError, HttpError, LifetimeLimitExceededError, NotWhitelistedError, OwnerNotConfiguredError, PROGRAM_IDS, PaymentParseError, PerTxLimitExceededError, SLOTS_PER_HOUR, SpendPolicyError, TOKEN_PROGRAM_ID, VaultFrozenError, ZeroAmountError, createAssociatedTokenAccountIdempotentInstruction, getAssociatedTokenAddress, paymentRequired, policyPda, serviceRegistryPda, vaultPda };
4300
+ export { ASSOCIATED_TOKEN_PROGRAM_ID, AccountNotFoundError, AgentFuel, AgentFuelError, HourlyLimitExceededError, HttpError, LifetimeLimitExceededError, NotWhitelistedError, OwnerNotConfiguredError, PROGRAM_IDS, PaymentParseError, PerTxLimitExceededError, ReceiptAlreadyRecordedError, RecordPaymentError, SLOTS_PER_HOUR, ServiceInactiveError, SpendPolicyError, TOKEN_PROGRAM_ID, VaultFrozenError, ZeroAmountError, agentProfilePda, agentServiceLinkPda, createAssociatedTokenAccountIdempotentInstruction, getAssociatedTokenAddress, pay, paymentRequired, pendingSpendPda, policyPda, receiptUsedPda, recordPayment, registerService, requestSpend, serviceRegistryPda, subscribeService, subscribeVault, vaultPda };
3336
4301
  //# sourceMappingURL=index.js.map
3337
4302
  //# sourceMappingURL=index.js.map