@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/CHANGELOG.md +22 -0
- package/README.md +15 -2
- package/dist/idl/credit-vault.cjs +475 -1
- package/dist/idl/credit-vault.cjs.map +1 -1
- package/dist/idl/credit-vault.d.cts +477 -1
- package/dist/idl/credit-vault.d.ts +477 -1
- package/dist/idl/credit-vault.js +475 -1
- package/dist/idl/credit-vault.js.map +1 -1
- package/dist/idl/reputation.cjs +128 -1
- package/dist/idl/reputation.cjs.map +1 -1
- package/dist/idl/reputation.d.cts +128 -1
- package/dist/idl/reputation.d.ts +128 -1
- package/dist/idl/reputation.js +128 -1
- package/dist/idl/reputation.js.map +1 -1
- package/dist/index.cjs +1035 -57
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +138 -1
- package/dist/index.d.ts +138 -1
- package/dist/index.js +1025 -60
- package/dist/index.js.map +1 -1
- package/package.json +6 -4
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: "
|
|
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: "
|
|
1958
|
+
name: "approve_spend",
|
|
1803
1959
|
discriminator: [
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
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: "
|
|
1816
|
-
|
|
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: "
|
|
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: "
|
|
2073
|
+
name: "cancel_spend",
|
|
1891
2074
|
discriminator: [
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
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: "
|
|
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
|
-
|
|
1952
|
-
|
|
2128
|
+
101,
|
|
2129
|
+
110,
|
|
2130
|
+
100,
|
|
1953
2131
|
105,
|
|
1954
|
-
|
|
1955
|
-
|
|
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: "
|
|
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: "
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
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
|
-
|
|
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
|