@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.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { BN, AnchorError,
|
|
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: "
|
|
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: "
|
|
1956
|
+
name: "approve_spend",
|
|
1801
1957
|
discriminator: [
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
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: "
|
|
1814
|
-
|
|
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: "
|
|
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: "
|
|
2071
|
+
name: "cancel_spend",
|
|
1889
2072
|
discriminator: [
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
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: "
|
|
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
|
-
|
|
1950
|
-
|
|
2126
|
+
101,
|
|
2127
|
+
110,
|
|
2128
|
+
100,
|
|
1951
2129
|
105,
|
|
1952
|
-
|
|
1953
|
-
|
|
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: "
|
|
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: "
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
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
|
-
|
|
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
|