@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.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();
@@ -187,6 +188,28 @@ var NotWhitelistedError = class extends SpendPolicyError {
187
188
  this.service = service;
188
189
  }
189
190
  };
191
+ var RecordPaymentError = class extends AgentFuelError {
192
+ constructor(message) {
193
+ super(message);
194
+ this.name = "RecordPaymentError";
195
+ }
196
+ };
197
+ var ReceiptAlreadyRecordedError = class extends RecordPaymentError {
198
+ receiptHash;
199
+ constructor(receiptHash) {
200
+ super("payment receipt was already recorded on chain");
201
+ this.name = "ReceiptAlreadyRecordedError";
202
+ this.receiptHash = receiptHash;
203
+ }
204
+ };
205
+ var ServiceInactiveError = class extends RecordPaymentError {
206
+ service;
207
+ constructor(service) {
208
+ super(`service ${service} is paused; record_payment rejected`);
209
+ this.name = "ServiceInactiveError";
210
+ this.service = service;
211
+ }
212
+ };
190
213
 
191
214
  // src/guardrails.ts
192
215
  function guardSpend(args) {
@@ -294,6 +317,12 @@ function wsUrl(apiBase, path) {
294
317
  if (apiBase.startsWith("http://")) return apiBase.replace(/^http/, "ws") + path;
295
318
  return apiBase + path;
296
319
  }
320
+ function subscribeService(apiBase, servicePubkey, opts) {
321
+ return subscribe(wsUrl(apiBase, `/ws/services/${servicePubkey}`), opts);
322
+ }
323
+ function subscribeVault(apiBase, vaultPubkey, opts) {
324
+ return subscribe(wsUrl(apiBase, `/ws/vaults/${vaultPubkey}`), opts);
325
+ }
297
326
 
298
327
  // src/idl/reputation.json
299
328
  var reputation_default = {
@@ -849,10 +878,14 @@ var reputation_default = {
849
878
  ],
850
879
  accounts: [
851
880
  {
852
- name: "service",
881
+ name: "sponsor",
853
882
  writable: true,
854
883
  signer: true
855
884
  },
885
+ {
886
+ name: "service",
887
+ signer: true
888
+ },
856
889
  {
857
890
  name: "service_registry",
858
891
  writable: true,
@@ -899,6 +932,15 @@ var reputation_default = {
899
932
  name: "ServiceCategory"
900
933
  }
901
934
  }
935
+ },
936
+ {
937
+ name: "service_uri",
938
+ type: {
939
+ array: [
940
+ "u8",
941
+ 128
942
+ ]
943
+ }
902
944
  }
903
945
  ]
904
946
  },
@@ -1014,6 +1056,61 @@ var reputation_default = {
1014
1056
  }
1015
1057
  }
1016
1058
  ]
1059
+ },
1060
+ {
1061
+ name: "set_service_active",
1062
+ discriminator: [
1063
+ 221,
1064
+ 172,
1065
+ 149,
1066
+ 49,
1067
+ 212,
1068
+ 184,
1069
+ 77,
1070
+ 101
1071
+ ],
1072
+ accounts: [
1073
+ {
1074
+ name: "service",
1075
+ signer: true
1076
+ },
1077
+ {
1078
+ name: "service_registry",
1079
+ writable: true,
1080
+ pda: {
1081
+ seeds: [
1082
+ {
1083
+ kind: "const",
1084
+ value: [
1085
+ 115,
1086
+ 101,
1087
+ 114,
1088
+ 118,
1089
+ 105,
1090
+ 99,
1091
+ 101
1092
+ ]
1093
+ },
1094
+ {
1095
+ kind: "account",
1096
+ path: "service"
1097
+ }
1098
+ ]
1099
+ }
1100
+ },
1101
+ {
1102
+ name: "authority",
1103
+ relations: [
1104
+ "service_registry"
1105
+ ]
1106
+ }
1107
+ ],
1108
+ args: [
1109
+ {
1110
+ name: "active",
1111
+ type: "bool"
1112
+ }
1113
+ ]
1017
1114
  }
1018
1115
  ],
1019
1116
  accounts: [
@@ -1162,6 +1259,19 @@ var reputation_default = {
1162
1259
  109
1163
1260
  ]
1164
1261
  },
1262
+ {
1263
+ name: "ServiceActiveSet",
1264
+ discriminator: [
1265
+ 151,
1266
+ 122,
1267
+ 7,
1268
+ 40,
1269
+ 191,
1270
+ 139,
1271
+ 237,
1272
+ 52
1273
+ ]
1274
+ },
1165
1275
  {
1166
1276
  name: "ServiceRegistered",
1167
1277
  discriminator: [
@@ -1226,6 +1336,11 @@ var reputation_default = {
1226
1336
  code: 6009,
1227
1337
  name: "FeedbackRateLimited",
1228
1338
  msg: "Feedback rate limit not yet expired for this (service, agent) pair"
1339
+ },
1340
+ {
1341
+ code: 6010,
1342
+ name: "UnauthorizedService",
1343
+ msg: "Only the service authority may perform this action"
1229
1344
  }
1230
1345
  ],
1231
1346
  types: [
@@ -1666,6 +1781,26 @@ var reputation_default = {
1666
1781
  ]
1667
1782
  }
1668
1783
  },
1784
+ {
1785
+ name: "ServiceActiveSet",
1786
+ type: {
1787
+ kind: "struct",
1788
+ fields: [
1789
+ {
1790
+ name: "service",
1791
+ type: "pubkey"
1792
+ },
1793
+ {
1794
+ name: "active",
1795
+ type: "bool"
1796
+ },
1797
+ {
1798
+ name: "slot",
1799
+ type: "u64"
1800
+ }
1801
+ ]
1802
+ }
1803
+ },
1669
1804
  {
1670
1805
  name: "ServiceCategory",
1671
1806
  type: {
@@ -1698,6 +1833,14 @@ var reputation_default = {
1698
1833
  name: "service",
1699
1834
  type: "pubkey"
1700
1835
  },
1836
+ {
1837
+ name: "sponsor",
1838
+ docs: [
1839
+ 'Wallet that paid rent. Lets us answer "who registered this service?"',
1840
+ "without an extra column on the on-chain account."
1841
+ ],
1842
+ type: "pubkey"
1843
+ },
1701
1844
  {
1702
1845
  name: "name",
1703
1846
  type: {
@@ -1740,6 +1883,19 @@ var reputation_default = {
1740
1883
  ]
1741
1884
  }
1742
1885
  },
1886
+ {
1887
+ name: "service_uri",
1888
+ docs: [
1889
+ "Off-chain metadata URI (pricing, docs, endpoint, logo). Padded to 128 bytes;",
1890
+ "trailing NULs are trimmed when read. Mirrors `AgentProfile::agent_uri`."
1891
+ ],
1892
+ type: {
1893
+ array: [
1894
+ "u8",
1895
+ 128
1896
+ ]
1897
+ }
1898
+ },
1743
1899
  {
1744
1900
  name: "category",
1745
1901
  type: {
@@ -1799,21 +1955,25 @@ var credit_vault_default = {
1799
1955
  },
1800
1956
  instructions: [
1801
1957
  {
1802
- name: "claim",
1958
+ name: "approve_spend",
1803
1959
  discriminator: [
1804
- 62,
1805
- 198,
1806
- 214,
1807
- 193,
1808
- 213,
1809
- 159,
1810
- 108,
1811
- 210
1960
+ 248,
1961
+ 201,
1962
+ 151,
1963
+ 15,
1964
+ 28,
1965
+ 162,
1966
+ 112,
1967
+ 90
1812
1968
  ],
1813
1969
  accounts: [
1814
1970
  {
1815
- name: "service",
1816
- signer: true
1971
+ name: "owner",
1972
+ writable: true,
1973
+ signer: true,
1974
+ relations: [
1975
+ "vault"
1976
+ ]
1817
1977
  },
1818
1978
  {
1819
1979
  name: "vault",
@@ -1832,8 +1992,7 @@ var credit_vault_default = {
1832
1992
  },
1833
1993
  {
1834
1994
  kind: "account",
1835
- path: "vault.owner",
1836
- account: "CreditVault"
1995
+ path: "owner"
1837
1996
  },
1838
1997
  {
1839
1998
  kind: "account",
@@ -1866,6 +2025,35 @@ var credit_vault_default = {
1866
2025
  ]
1867
2026
  }
1868
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
+ },
1869
2057
  {
1870
2058
  name: "vault_token_account",
1871
2059
  writable: true
@@ -1879,43 +2067,31 @@ var credit_vault_default = {
1879
2067
  address: "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
1880
2068
  }
1881
2069
  ],
1882
- args: [
1883
- {
1884
- name: "amount_usdc",
1885
- type: "u64"
1886
- }
1887
- ]
2070
+ args: []
1888
2071
  },
1889
2072
  {
1890
- name: "create_vault",
2073
+ name: "cancel_spend",
1891
2074
  discriminator: [
1892
- 29,
1893
- 237,
1894
- 247,
1895
- 208,
1896
- 193,
1897
- 82,
1898
- 54,
1899
- 135
2075
+ 122,
2076
+ 254,
2077
+ 101,
2078
+ 132,
2079
+ 241,
2080
+ 232,
2081
+ 205,
2082
+ 179
1900
2083
  ],
1901
2084
  accounts: [
1902
2085
  {
1903
2086
  name: "owner",
1904
2087
  writable: true,
1905
- signer: true
1906
- },
1907
- {
1908
- name: "agent",
1909
- docs: [
1910
- "account need not exist on chain; we never read or write its data."
2088
+ signer: true,
2089
+ relations: [
2090
+ "vault"
1911
2091
  ]
1912
2092
  },
1913
- {
1914
- name: "usdc_mint"
1915
- },
1916
2093
  {
1917
2094
  name: "vault",
1918
- writable: true,
1919
2095
  pda: {
1920
2096
  seeds: [
1921
2097
  {
@@ -1934,13 +2110,14 @@ var credit_vault_default = {
1934
2110
  },
1935
2111
  {
1936
2112
  kind: "account",
1937
- path: "agent"
2113
+ path: "vault.agent",
2114
+ account: "CreditVault"
1938
2115
  }
1939
2116
  ]
1940
2117
  }
1941
2118
  },
1942
2119
  {
1943
- name: "policy",
2120
+ name: "pending_spend",
1944
2121
  writable: true,
1945
2122
  pda: {
1946
2123
  seeds: [
@@ -1948,38 +2125,211 @@ var credit_vault_default = {
1948
2125
  kind: "const",
1949
2126
  value: [
1950
2127
  112,
1951
- 111,
1952
- 108,
2128
+ 101,
2129
+ 110,
2130
+ 100,
1953
2131
  105,
1954
- 99,
1955
- 121
2132
+ 110,
2133
+ 103
1956
2134
  ]
1957
2135
  },
1958
2136
  {
1959
2137
  kind: "account",
1960
2138
  path: "vault"
2139
+ },
2140
+ {
2141
+ kind: "account",
2142
+ path: "pending_spend.nonce",
2143
+ account: "PendingSpend"
1961
2144
  }
1962
2145
  ]
1963
2146
  }
2147
+ }
2148
+ ],
2149
+ args: []
2150
+ },
2151
+ {
2152
+ name: "claim",
2153
+ discriminator: [
2154
+ 62,
2155
+ 198,
2156
+ 214,
2157
+ 193,
2158
+ 213,
2159
+ 159,
2160
+ 108,
2161
+ 210
2162
+ ],
2163
+ accounts: [
2164
+ {
2165
+ name: "service",
2166
+ signer: true
1964
2167
  },
1965
2168
  {
1966
- name: "vault_token_account",
2169
+ name: "vault",
1967
2170
  writable: true,
1968
2171
  pda: {
1969
2172
  seeds: [
2173
+ {
2174
+ kind: "const",
2175
+ value: [
2176
+ 118,
2177
+ 97,
2178
+ 117,
2179
+ 108,
2180
+ 116
2181
+ ]
2182
+ },
1970
2183
  {
1971
2184
  kind: "account",
1972
- path: "vault"
2185
+ path: "vault.owner",
2186
+ account: "CreditVault"
1973
2187
  },
1974
2188
  {
1975
- kind: "const",
1976
- value: [
1977
- 6,
1978
- 221,
1979
- 246,
1980
- 225,
1981
- 215,
1982
- 101,
2189
+ kind: "account",
2190
+ path: "vault.agent",
2191
+ account: "CreditVault"
2192
+ }
2193
+ ]
2194
+ }
2195
+ },
2196
+ {
2197
+ name: "policy",
2198
+ writable: true,
2199
+ pda: {
2200
+ seeds: [
2201
+ {
2202
+ kind: "const",
2203
+ value: [
2204
+ 112,
2205
+ 111,
2206
+ 108,
2207
+ 105,
2208
+ 99,
2209
+ 121
2210
+ ]
2211
+ },
2212
+ {
2213
+ kind: "account",
2214
+ path: "vault"
2215
+ }
2216
+ ]
2217
+ }
2218
+ },
2219
+ {
2220
+ name: "vault_token_account",
2221
+ writable: true
2222
+ },
2223
+ {
2224
+ name: "service_token_account",
2225
+ writable: true
2226
+ },
2227
+ {
2228
+ name: "token_program",
2229
+ address: "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
2230
+ }
2231
+ ],
2232
+ args: [
2233
+ {
2234
+ name: "amount_usdc",
2235
+ type: "u64"
2236
+ }
2237
+ ]
2238
+ },
2239
+ {
2240
+ name: "create_vault",
2241
+ discriminator: [
2242
+ 29,
2243
+ 237,
2244
+ 247,
2245
+ 208,
2246
+ 193,
2247
+ 82,
2248
+ 54,
2249
+ 135
2250
+ ],
2251
+ accounts: [
2252
+ {
2253
+ name: "owner",
2254
+ writable: true,
2255
+ signer: true
2256
+ },
2257
+ {
2258
+ name: "agent",
2259
+ docs: [
2260
+ "account need not exist on chain; we never read or write its data."
2261
+ ]
2262
+ },
2263
+ {
2264
+ name: "usdc_mint"
2265
+ },
2266
+ {
2267
+ name: "vault",
2268
+ writable: true,
2269
+ pda: {
2270
+ seeds: [
2271
+ {
2272
+ kind: "const",
2273
+ value: [
2274
+ 118,
2275
+ 97,
2276
+ 117,
2277
+ 108,
2278
+ 116
2279
+ ]
2280
+ },
2281
+ {
2282
+ kind: "account",
2283
+ path: "owner"
2284
+ },
2285
+ {
2286
+ kind: "account",
2287
+ path: "agent"
2288
+ }
2289
+ ]
2290
+ }
2291
+ },
2292
+ {
2293
+ name: "policy",
2294
+ writable: true,
2295
+ pda: {
2296
+ seeds: [
2297
+ {
2298
+ kind: "const",
2299
+ value: [
2300
+ 112,
2301
+ 111,
2302
+ 108,
2303
+ 105,
2304
+ 99,
2305
+ 121
2306
+ ]
2307
+ },
2308
+ {
2309
+ kind: "account",
2310
+ path: "vault"
2311
+ }
2312
+ ]
2313
+ }
2314
+ },
2315
+ {
2316
+ name: "vault_token_account",
2317
+ writable: true,
2318
+ pda: {
2319
+ seeds: [
2320
+ {
2321
+ kind: "account",
2322
+ path: "vault"
2323
+ },
2324
+ {
2325
+ kind: "const",
2326
+ value: [
2327
+ 6,
2328
+ 221,
2329
+ 246,
2330
+ 225,
2331
+ 215,
2332
+ 101,
1983
2333
  161,
1984
2334
  147,
1985
2335
  217,
@@ -2204,6 +2554,104 @@ var credit_vault_default = {
2204
2554
  ],
2205
2555
  args: []
2206
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
+ },
2207
2655
  {
2208
2656
  name: "spend",
2209
2657
  discriminator: [
@@ -2529,6 +2977,19 @@ var credit_vault_default = {
2529
2977
  70
2530
2978
  ]
2531
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
+ },
2532
2993
  {
2533
2994
  name: "SpendPolicy",
2534
2995
  discriminator: [
@@ -2583,6 +3044,32 @@ var credit_vault_default = {
2583
3044
  161
2584
3045
  ]
2585
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
+ },
2586
3073
  {
2587
3074
  name: "Spent",
2588
3075
  discriminator: [
@@ -2699,6 +3186,16 @@ var credit_vault_default = {
2699
3186
  code: 6009,
2700
3187
  name: "PostPayDisabled",
2701
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"
2702
3199
  }
2703
3200
  ],
2704
3201
  types: [
@@ -2787,12 +3284,22 @@ var credit_vault_default = {
2787
3284
  name: "bump",
2788
3285
  type: "u8"
2789
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
+ },
2790
3297
  {
2791
3298
  name: "_padding",
2792
3299
  type: {
2793
3300
  array: [
2794
3301
  "u8",
2795
- 64
3302
+ 56
2796
3303
  ]
2797
3304
  }
2798
3305
  }
@@ -2827,6 +3334,65 @@ var credit_vault_default = {
2827
3334
  ]
2828
3335
  }
2829
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
+ },
2830
3396
  {
2831
3397
  name: "PolicyUpdated",
2832
3398
  type: {
@@ -2930,6 +3496,70 @@ var credit_vault_default = {
2930
3496
  ]
2931
3497
  }
2932
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
+ },
2933
3563
  {
2934
3564
  name: "Spent",
2935
3565
  type: {
@@ -3096,6 +3726,43 @@ function serviceRegistryPda(serviceAuthority) {
3096
3726
  );
3097
3727
  return pda;
3098
3728
  }
3729
+ function agentProfilePda(agent) {
3730
+ const [pda] = web3_js.PublicKey.findProgramAddressSync(
3731
+ [Buffer.from("agent"), toPubkey(agent).toBuffer()],
3732
+ PROGRAM_IDS.reputation
3733
+ );
3734
+ return pda;
3735
+ }
3736
+ function agentServiceLinkPda(agentProfile, serviceRegistry) {
3737
+ const [pda] = web3_js.PublicKey.findProgramAddressSync(
3738
+ [
3739
+ Buffer.from("link"),
3740
+ toPubkey(agentProfile).toBuffer(),
3741
+ toPubkey(serviceRegistry).toBuffer()
3742
+ ],
3743
+ PROGRAM_IDS.reputation
3744
+ );
3745
+ return pda;
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
+ }
3756
+ function receiptUsedPda(receiptHash) {
3757
+ if (receiptHash.length !== 32) {
3758
+ throw new Error(`receiptUsedPda expects a 32-byte hash, got ${receiptHash.length}`);
3759
+ }
3760
+ const [pda] = web3_js.PublicKey.findProgramAddressSync(
3761
+ [Buffer.from("receipt"), Buffer.from(receiptHash)],
3762
+ PROGRAM_IDS.reputation
3763
+ );
3764
+ return pda;
3765
+ }
3099
3766
  function buildProvider(connection, keypair) {
3100
3767
  return new anchor.AnchorProvider(connection, new anchor.Wallet(keypair), anchor.AnchorProvider.defaultOptions());
3101
3768
  }
@@ -3106,6 +3773,207 @@ function reputationProgram(provider) {
3106
3773
  return new anchor.Program(reputation_default, provider);
3107
3774
  }
3108
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
+
3109
3977
  // src/client.ts
3110
3978
  var DEFAULT_API_BASE = "http://localhost:8080";
3111
3979
  var AgentFuel = class {
@@ -3204,6 +4072,53 @@ var AgentFuel = class {
3204
4072
  throw mapSpendError(err, { service, amountUsdc, vault, policy });
3205
4073
  }
3206
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
+ }
4107
+ /// Triggers an on-chain recomputation of the agent's reputation score.
4108
+ /// Permissionless — any signer can call it; we use the agent itself since
4109
+ /// the SDK already has its keypair available and it already pays tx fees
4110
+ /// for spends. The instruction reads the agent's already-public counters
4111
+ /// (volume, diversity, streak, tenure, feedback), recalculates the score
4112
+ /// to a single u16 ≤ 1000, and emits a `ScoreComputed` event. The webhook
4113
+ /// picks that up; the next `getScore()` returns the fresh value.
4114
+ async computeScore() {
4115
+ const profile = agentProfilePda(this.agentPubkey);
4116
+ const signature = await this.reputation.methods.computeScore().accounts({
4117
+ caller: this.agentPubkey,
4118
+ agentProfile: profile
4119
+ }).signers([this.agent]).rpc();
4120
+ return { signature };
4121
+ }
3207
4122
  onEvent(callback, options) {
3208
4123
  const target = options?.agent ? toPubkey(options.agent) : this.agentPubkey;
3209
4124
  const url = wsUrl(this.apiBase, `/ws/agents/${target.toBase58()}`);
@@ -3248,6 +4163,56 @@ async function safeText(res) {
3248
4163
  return void 0;
3249
4164
  }
3250
4165
  }
4166
+ async function recordPayment(args) {
4167
+ const { service, connection, amountUsdc } = args;
4168
+ const agentPubkey = toPubkey(args.agent);
4169
+ if (amountUsdc <= 0) {
4170
+ throw new Error("recordPayment: amountUsdc must be > 0");
4171
+ }
4172
+ if (args.receiptHash.length !== 32) {
4173
+ throw new Error(
4174
+ `recordPayment: receiptHash must be 32 bytes, got ${args.receiptHash.length}`
4175
+ );
4176
+ }
4177
+ const provider = buildProvider(connection, service);
4178
+ const program = reputationProgram(provider);
4179
+ const agentProfile = agentProfilePda(agentPubkey);
4180
+ const serviceRegistry = serviceRegistryPda(service.publicKey);
4181
+ const link = agentServiceLinkPda(agentProfile, serviceRegistry);
4182
+ const receipt = receiptUsedPda(args.receiptHash);
4183
+ try {
4184
+ const signature = await program.methods.recordPayment(new anchor.BN(amountUsdc), args.receiptHash).accounts({
4185
+ service: service.publicKey,
4186
+ agentProfile,
4187
+ serviceRegistry,
4188
+ agentServiceLink: link,
4189
+ receiptUsed: receipt,
4190
+ systemProgram: web3_js.SystemProgram.programId
4191
+ }).signers([service]).rpc();
4192
+ return { signature };
4193
+ } catch (err) {
4194
+ throw mapRecordPaymentError(err, args.receiptHash);
4195
+ }
4196
+ }
4197
+ function mapRecordPaymentError(err, receiptHash) {
4198
+ const message = err instanceof Error ? err.message : String(err);
4199
+ if (/already in use/i.test(message)) {
4200
+ return new ReceiptAlreadyRecordedError(receiptHash);
4201
+ }
4202
+ if (!(err instanceof anchor.AnchorError)) return err;
4203
+ switch (err.error.errorCode.number) {
4204
+ case 6e3:
4205
+ return new RecordPaymentError("counter overflow on chain");
4206
+ case 6001:
4207
+ return new ServiceInactiveError(
4208
+ err.error.origin?.toString() ?? "<unknown service>"
4209
+ );
4210
+ case 6002:
4211
+ return new ZeroAmountError();
4212
+ default:
4213
+ return err;
4214
+ }
4215
+ }
3251
4216
 
3252
4217
  // src/x402.ts
3253
4218
  var HEADER = "X-Payment-Required";
@@ -3346,16 +4311,29 @@ exports.OwnerNotConfiguredError = OwnerNotConfiguredError;
3346
4311
  exports.PROGRAM_IDS = PROGRAM_IDS;
3347
4312
  exports.PaymentParseError = PaymentParseError;
3348
4313
  exports.PerTxLimitExceededError = PerTxLimitExceededError;
4314
+ exports.ReceiptAlreadyRecordedError = ReceiptAlreadyRecordedError;
4315
+ exports.RecordPaymentError = RecordPaymentError;
3349
4316
  exports.SLOTS_PER_HOUR = SLOTS_PER_HOUR;
4317
+ exports.ServiceInactiveError = ServiceInactiveError;
3350
4318
  exports.SpendPolicyError = SpendPolicyError;
3351
4319
  exports.TOKEN_PROGRAM_ID = TOKEN_PROGRAM_ID;
3352
4320
  exports.VaultFrozenError = VaultFrozenError;
3353
4321
  exports.ZeroAmountError = ZeroAmountError;
4322
+ exports.agentProfilePda = agentProfilePda;
4323
+ exports.agentServiceLinkPda = agentServiceLinkPda;
3354
4324
  exports.createAssociatedTokenAccountIdempotentInstruction = createAssociatedTokenAccountIdempotentInstruction;
3355
4325
  exports.getAssociatedTokenAddress = getAssociatedTokenAddress;
4326
+ exports.pay = pay;
3356
4327
  exports.paymentRequired = paymentRequired;
4328
+ exports.pendingSpendPda = pendingSpendPda;
3357
4329
  exports.policyPda = policyPda;
4330
+ exports.receiptUsedPda = receiptUsedPda;
4331
+ exports.recordPayment = recordPayment;
4332
+ exports.registerService = registerService;
4333
+ exports.requestSpend = requestSpend;
3358
4334
  exports.serviceRegistryPda = serviceRegistryPda;
4335
+ exports.subscribeService = subscribeService;
4336
+ exports.subscribeVault = subscribeVault;
3359
4337
  exports.vaultPda = vaultPda;
3360
4338
  //# sourceMappingURL=index.cjs.map
3361
4339
  //# sourceMappingURL=index.cjs.map