@augustdigital/sdk 5.1.1 → 7.0.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.
Files changed (72) hide show
  1. package/lib/adapters/evm/getters.d.ts +1 -1
  2. package/lib/adapters/evm/getters.js +14 -19
  3. package/lib/adapters/evm/index.d.ts +8 -1
  4. package/lib/adapters/evm/index.js +24 -0
  5. package/lib/adapters/solana/index.d.ts +4 -4
  6. package/lib/adapters/solana/utils.d.ts +5 -4
  7. package/lib/adapters/solana/utils.js +82 -45
  8. package/lib/adapters/solana/vault.actions.d.ts +2 -2
  9. package/lib/adapters/solana/vault.actions.js +112 -74
  10. package/lib/adapters/stellar/actions.js +3 -2
  11. package/lib/adapters/stellar/constants.d.ts +2 -0
  12. package/lib/adapters/stellar/constants.js +3 -1
  13. package/lib/adapters/stellar/getters.js +2 -2
  14. package/lib/adapters/stellar/soroban.js +19 -8
  15. package/lib/adapters/stellar/submit.js +16 -6
  16. package/lib/adapters/stellar/utils.d.ts +2 -1
  17. package/lib/adapters/stellar/utils.js +7 -15
  18. package/lib/adapters/sui/utils.d.ts +1 -1
  19. package/lib/adapters/sui/utils.js +3 -7
  20. package/lib/core/analytics/chain-name.d.ts +1 -0
  21. package/lib/core/analytics/chain-name.js +26 -0
  22. package/lib/core/analytics/env.d.ts +4 -0
  23. package/lib/core/analytics/env.js +33 -0
  24. package/lib/core/analytics/index.d.ts +6 -2
  25. package/lib/core/analytics/index.js +16 -1
  26. package/lib/core/analytics/instrumentation.js +56 -48
  27. package/lib/core/analytics/method-taxonomy.d.ts +3 -0
  28. package/lib/core/analytics/method-taxonomy.js +82 -0
  29. package/lib/core/analytics/metrics.js +18 -42
  30. package/lib/core/analytics/sanitize.d.ts +1 -0
  31. package/lib/core/analytics/sanitize.js +34 -0
  32. package/lib/core/analytics/sentry-runtime.d.ts +4 -0
  33. package/lib/core/analytics/sentry-runtime.js +78 -0
  34. package/lib/core/analytics/sentry.d.ts +7 -1
  35. package/lib/core/analytics/sentry.js +107 -51
  36. package/lib/core/analytics/types.d.ts +2 -0
  37. package/lib/core/analytics/version.d.ts +1 -0
  38. package/lib/core/analytics/version.js +5 -0
  39. package/lib/core/base.class.d.ts +2 -1
  40. package/lib/core/base.class.js +5 -1
  41. package/lib/core/cache.d.ts +4 -0
  42. package/lib/core/cache.js +25 -0
  43. package/lib/core/constants/web3.js +1 -1
  44. package/lib/core/fetcher.d.ts +4 -4
  45. package/lib/core/fetcher.js +49 -60
  46. package/lib/core/helpers/chain-address.d.ts +3 -0
  47. package/lib/core/helpers/chain-address.js +36 -0
  48. package/lib/core/helpers/explorer-link.d.ts +2 -0
  49. package/lib/core/helpers/explorer-link.js +11 -0
  50. package/lib/core/helpers/vault-version.d.ts +4 -0
  51. package/lib/core/helpers/vault-version.js +59 -0
  52. package/lib/core/helpers/vaults.d.ts +3 -4
  53. package/lib/core/helpers/vaults.js +12 -62
  54. package/lib/core/helpers/web3.d.ts +6 -6
  55. package/lib/core/helpers/web3.js +142 -79
  56. package/lib/core/logger/slack.js +2 -2
  57. package/lib/core/vault-metadata.d.ts +6 -0
  58. package/lib/core/vault-metadata.js +36 -0
  59. package/lib/evm/methods/crossChainVault.js +72 -16
  60. package/lib/evm/types/crossChain.d.ts +4 -0
  61. package/lib/evm/types/crossChain.js +6 -0
  62. package/lib/modules/vaults/fetcher.d.ts +1 -6
  63. package/lib/modules/vaults/fetcher.js +27 -36
  64. package/lib/modules/vaults/getters.d.ts +1 -1
  65. package/lib/modules/vaults/getters.js +3 -2
  66. package/lib/modules/vaults/read.actions.d.ts +27 -0
  67. package/lib/modules/vaults/read.actions.js +220 -0
  68. package/lib/modules/vaults/utils/date-utils.js +1 -2
  69. package/lib/modules/vaults/utils.js +57 -36
  70. package/lib/modules/vaults/write.actions.d.ts +35 -2
  71. package/lib/modules/vaults/write.actions.js +254 -94
  72. package/package.json +5 -2
@@ -1,6 +1,15 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.safeBigInt = safeBigInt;
4
+ exports.resolveDepositTokenDecimals = resolveDepositTokenDecimals;
5
+ exports.resolveSpender = resolveSpender;
6
+ exports.validateAmountPrecision = validateAmountPrecision;
7
+ exports.isNonceParsing = isNonceParsing;
8
+ exports.safeWaitForTx = safeWaitForTx;
9
+ exports.safeSendTx = safeSendTx;
10
+ exports.tryRecoverTxHash = tryRecoverTxHash;
3
11
  exports.vaultApprove = vaultApprove;
12
+ exports.approve = approve;
4
13
  exports.vaultDeposit = vaultDeposit;
5
14
  exports.vaultRequestRedeem = vaultRequestRedeem;
6
15
  exports.vaultRedeem = vaultRedeem;
@@ -9,22 +18,57 @@ exports.rwaRedeemAsset = rwaRedeemAsset;
9
18
  const ethers_1 = require("ethers");
10
19
  const abis_1 = require("../../abis");
11
20
  const core_1 = require("../../core");
12
- const read_actions_1 = require("./read.actions");
13
21
  const adapter_helpers_1 = require("./adapter.helpers");
14
22
  const utils_1 = require("./utils");
15
- function safeBigInt(value) {
23
+ function safeBigInt(value, context = 'safeBigInt') {
16
24
  if (value === null || value === undefined)
17
25
  return 0n;
18
26
  const s = String(value);
19
- if (s === '0x' || s === '')
27
+ if (s === '' || s === '0x') {
28
+ if (s === '0x') {
29
+ core_1.Logger.log.warn(context, 'RPC returned bare "0x"; treating as 0', {
30
+ raw: s,
31
+ });
32
+ }
20
33
  return 0n;
34
+ }
21
35
  try {
22
36
  return BigInt(s);
23
37
  }
24
- catch {
38
+ catch (err) {
39
+ core_1.Logger.log.warn(context, 'Could not parse RPC value as BigInt; treating as 0', { raw: s, error: String(err) });
25
40
  return 0n;
26
41
  }
27
42
  }
43
+ async function resolveDepositTokenDecimals(args) {
44
+ const { actualDepositAsset, underlyingAsset, isNativeToken, isMultiAssetVault, vaultDecimals, readErc20Decimals, } = args;
45
+ if (isNativeToken)
46
+ return 18;
47
+ const isUnderlying = actualDepositAsset.toLowerCase() === underlyingAsset.toLowerCase();
48
+ if (isUnderlying && !isMultiAssetVault)
49
+ return vaultDecimals;
50
+ return readErc20Decimals(actualDepositAsset);
51
+ }
52
+ function resolveSpender(args) {
53
+ if (args.isMultiAssetVault)
54
+ return args.target;
55
+ if (args.isAdapterDeposit && args.adapterWrapperAddress)
56
+ return args.adapterWrapperAddress;
57
+ return args.target;
58
+ }
59
+ function validateAmountPrecision(amount) {
60
+ if (typeof amount === 'string' || typeof amount === 'bigint')
61
+ return;
62
+ if (!Number.isFinite(amount)) {
63
+ throw new core_1.AugustValidationError('INVALID_INPUT', `amount must be finite, got ${amount}`);
64
+ }
65
+ if (amount < 0) {
66
+ throw new core_1.AugustValidationError('INVALID_INPUT', `amount must be non-negative, got ${amount}`);
67
+ }
68
+ if (Number.isInteger(amount) && !Number.isSafeInteger(amount)) {
69
+ throw new core_1.AugustValidationError('INVALID_INPUT', `amount ${amount} exceeds Number.MAX_SAFE_INTEGER; pass a string or bigint to preserve precision`);
70
+ }
71
+ }
28
72
  const SAFE_WAIT_TIMEOUT_MS = 120000;
29
73
  function isNonceParsing(error) {
30
74
  const code = error?.code;
@@ -100,64 +144,142 @@ async function tryRecoverTxHash(error, signer, wait) {
100
144
  }
101
145
  return txHash;
102
146
  }
103
- async function vaultApprove(signer, options) {
104
- const { wallet, target, wait, amount } = options;
147
+ async function approveCore(signer, options) {
148
+ const { wallet, target, wait, amount, depositAsset } = options;
105
149
  const [goodWallet, goodPool] = [
106
150
  (0, core_1.checkAddress)(wallet, console, 'wallet'),
107
151
  (0, core_1.checkAddress)(target, console),
108
152
  ];
109
- if (!goodWallet || !goodPool || !amount)
110
- return;
111
- const _allowance = await (0, read_actions_1.vaultAllowance)(signer, { target, wallet });
112
- if (!_allowance || _allowance?.raw === '0') {
113
- try {
114
- const poolContract = (0, core_1.createContract)({
153
+ if (!goodWallet || !goodPool) {
154
+ throw new core_1.AugustValidationError('INVALID_ADDRESS', `vaultApprove: invalid ${!goodWallet ? 'wallet' : 'target'} address`);
155
+ }
156
+ if (amount === undefined || amount === null) {
157
+ throw new core_1.AugustValidationError('INVALID_INPUT', 'vaultApprove: amount is required');
158
+ }
159
+ validateAmountPrecision(amount);
160
+ try {
161
+ const tokenizedVault = (await (0, core_1.fetchTokenizedVault)(target))?.[0];
162
+ const vaultVersion = (0, core_1.getVaultVersionV2)(tokenizedVault);
163
+ const adapterConfig = (0, core_1.getVaultAdapterConfig)(target);
164
+ const isMultiAssetVault = vaultVersion === 'evm-2';
165
+ const poolContract = isMultiAssetVault
166
+ ? (0, core_1.createContract)({
167
+ address: target,
168
+ provider: signer,
169
+ abi: abis_1.ABI_TOKENIZED_VAULT_V2,
170
+ })
171
+ : (0, core_1.createContract)({
115
172
  address: target,
116
173
  provider: signer,
117
174
  abi: abis_1.ABI_LENDING_POOLS,
118
175
  });
119
- const [asset, rawDecimals] = await Promise.all([
176
+ let underlyingAsset;
177
+ let vaultDecimals;
178
+ if (isMultiAssetVault) {
179
+ const [asset, receiptTokenAddr] = await Promise.all([
120
180
  poolContract.asset(),
121
- poolContract.decimals(),
181
+ poolContract.lpTokenAddress(),
122
182
  ]);
123
- const decimals = Number(rawDecimals);
124
- const normalizedAmt = (0, core_1.toNormalizedBn)(amount, decimals);
125
- const depositTokenContract = (0, core_1.createContract)({
126
- address: asset,
127
- abi: abis_1.ABI_ERC20,
183
+ underlyingAsset = asset;
184
+ const receiptContract = (0, core_1.createContract)({
185
+ address: receiptTokenAddr,
128
186
  provider: signer,
187
+ abi: abis_1.ABI_ERC20,
129
188
  });
130
- const { hash: approvalHash } = await safeSendTx(() => depositTokenContract
131
- .connect(signer)
132
- .approve(target, normalizedAmt.raw), signer, wait);
133
- core_1.Logger.log.info('approve:tx_hash', approvalHash);
134
- return approvalHash;
189
+ vaultDecimals = Number(await receiptContract.decimals());
135
190
  }
136
- catch (e) {
137
- core_1.Logger.log.error('approve', e, { target, amount });
138
- throw new Error(`Approval failed: ${e instanceof Error ? e.message : 'Unknown error'}`);
191
+ else {
192
+ const [asset, rawDecimals] = await Promise.all([
193
+ poolContract.asset(),
194
+ poolContract.decimals(),
195
+ ]);
196
+ underlyingAsset = asset;
197
+ vaultDecimals = Number(rawDecimals);
139
198
  }
199
+ const actualDepositAsset = (depositAsset || underlyingAsset);
200
+ const isNativeToken = actualDepositAsset === ethers_1.ZeroAddress ||
201
+ actualDepositAsset === '0x0000000000000000000000000000000000000000';
202
+ if (isNativeToken)
203
+ return { kind: 'native' };
204
+ const isAdapterDeposit = actualDepositAsset.toLowerCase() !== underlyingAsset.toLowerCase();
205
+ const spenderAddress = resolveSpender({
206
+ target,
207
+ isMultiAssetVault,
208
+ isAdapterDeposit,
209
+ adapterWrapperAddress: adapterConfig?.wrapperAddress,
210
+ });
211
+ const depositTokenDecimals = await resolveDepositTokenDecimals({
212
+ actualDepositAsset,
213
+ underlyingAsset,
214
+ isNativeToken: false,
215
+ isMultiAssetVault,
216
+ vaultDecimals,
217
+ readErc20Decimals: async (addr) => {
218
+ const erc20 = (0, core_1.createContract)({
219
+ address: addr,
220
+ provider: signer,
221
+ abi: abis_1.ABI_ERC20,
222
+ });
223
+ return Number(await erc20.decimals());
224
+ },
225
+ });
226
+ const normalizedAmt = (0, core_1.toNormalizedBn)(amount, depositTokenDecimals);
227
+ const needed = BigInt(normalizedAmt.raw);
228
+ const tokenContract = (0, core_1.createContract)({
229
+ address: actualDepositAsset,
230
+ abi: abis_1.ABI_ERC20,
231
+ provider: signer,
232
+ });
233
+ const currentAllowance = await tokenContract.allowance(wallet, spenderAddress);
234
+ const existing = safeBigInt(currentAllowance, 'vaultApprove:allowance');
235
+ if (existing >= needed) {
236
+ core_1.Logger.log.info('approve:allowance-sufficient', {
237
+ target,
238
+ spender: spenderAddress,
239
+ amount,
240
+ });
241
+ return { kind: 'sufficient', existing };
242
+ }
243
+ const { hash: approvalHash } = await safeSendTx(() => tokenContract
244
+ .connect(signer)
245
+ .approve(spenderAddress, normalizedAmt.raw), signer, wait);
246
+ core_1.Logger.log.info('approve:tx_hash', approvalHash);
247
+ return { kind: 'sent', hash: approvalHash };
140
248
  }
141
- else {
142
- core_1.Logger.log.info('approve:allowance', _allowance.normalized, 'amount:', amount);
249
+ catch (e) {
250
+ if (e instanceof core_1.AugustSDKError)
251
+ throw e;
252
+ core_1.Logger.log.error('vaultApprove', e, { target, amount });
253
+ throw new core_1.AugustSDKError('UNKNOWN', `Approval failed: ${e instanceof Error ? e.message : 'Unknown error'}`, { cause: e, context: { target, amount } });
143
254
  }
144
255
  }
256
+ async function vaultApprove(signer, options) {
257
+ const result = await approveCore(signer, options);
258
+ return result.kind === 'sent' ? result.hash : undefined;
259
+ }
260
+ async function approve(signer, options) {
261
+ return approveCore(signer, options);
262
+ }
145
263
  async function vaultDeposit(signer, options) {
146
264
  const { wallet, target, wait, amount, depositAsset, chainId, poolName } = options;
147
265
  const [goodWallet, goodPool] = [
148
266
  (0, core_1.checkAddress)(wallet, console, 'wallet'),
149
267
  (0, core_1.checkAddress)(target, console),
150
268
  ];
151
- if (!goodWallet || !goodPool)
152
- return;
269
+ if (!goodWallet || !goodPool) {
270
+ throw new core_1.AugustValidationError('INVALID_ADDRESS', `vaultDeposit: invalid ${!goodWallet ? 'wallet' : 'target'} address`);
271
+ }
272
+ if (amount === undefined || amount === null) {
273
+ throw new core_1.AugustValidationError('INVALID_INPUT', 'vaultDeposit: amount is required');
274
+ }
275
+ validateAmountPrecision(amount);
153
276
  try {
154
277
  const tokenizedVault = (await (0, core_1.fetchTokenizedVault)(target))?.[0];
155
278
  const vaultVersion = (0, core_1.getVaultVersionV2)(tokenizedVault);
156
279
  const adapterConfig = (0, core_1.getVaultAdapterConfig)(target);
157
280
  let poolContract;
158
281
  let underlyingAsset;
159
- let decimals;
160
- let depositTokenDecimals;
282
+ let vaultDecimals;
161
283
  if (vaultVersion === 'evm-2') {
162
284
  poolContract = (0, core_1.createContract)({
163
285
  address: target,
@@ -176,7 +298,7 @@ async function vaultDeposit(signer, options) {
176
298
  provider: signer,
177
299
  abi: abis_1.ABI_ERC20,
178
300
  });
179
- decimals = Number(await receiptContract.decimals());
301
+ vaultDecimals = Number(await receiptContract.decimals());
180
302
  }
181
303
  else {
182
304
  poolContract = (0, core_1.createContract)({
@@ -188,7 +310,7 @@ async function vaultDeposit(signer, options) {
188
310
  poolContract.asset(),
189
311
  poolContract.decimals(),
190
312
  ]);
191
- decimals = Number(rawDecimals);
313
+ vaultDecimals = Number(rawDecimals);
192
314
  underlyingAsset = fetchedUnderlyingAsset;
193
315
  }
194
316
  const actualDepositAsset = depositAsset || underlyingAsset;
@@ -196,39 +318,43 @@ async function vaultDeposit(signer, options) {
196
318
  actualDepositAsset === '0x0000000000000000000000000000000000000000';
197
319
  const isAdapterDeposit = actualDepositAsset.toLowerCase() !== underlyingAsset.toLowerCase();
198
320
  const isMultiAssetVault = vaultVersion === 'evm-2';
199
- if (isAdapterDeposit && !isNativeToken) {
200
- const depositTokenContract = (0, core_1.createContract)({
201
- address: actualDepositAsset,
202
- provider: signer,
203
- abi: abis_1.ABI_ERC20,
204
- });
205
- depositTokenDecimals = Number(await depositTokenContract.decimals());
321
+ if (isAdapterDeposit && !isMultiAssetVault && !adapterConfig) {
322
+ throw new core_1.AugustValidationError('INVALID_INPUT', `vaultDeposit: depositAsset ${actualDepositAsset} differs from vault underlying ${underlyingAsset} but no adapter is configured for vault ${target}`);
206
323
  }
207
- else {
208
- depositTokenDecimals = decimals;
209
- }
210
- const normalizedAmt = (0, core_1.toNormalizedBn)(amount, isNativeToken ? decimals : depositTokenDecimals);
324
+ const depositTokenDecimals = await resolveDepositTokenDecimals({
325
+ actualDepositAsset,
326
+ underlyingAsset,
327
+ isNativeToken,
328
+ isMultiAssetVault,
329
+ vaultDecimals,
330
+ readErc20Decimals: async (addr) => {
331
+ const erc20 = (0, core_1.createContract)({
332
+ address: addr,
333
+ provider: signer,
334
+ abi: abis_1.ABI_ERC20,
335
+ });
336
+ return Number(await erc20.decimals());
337
+ },
338
+ });
339
+ const normalizedAmt = (0, core_1.toNormalizedBn)(amount, depositTokenDecimals);
211
340
  if (!isNativeToken) {
212
- let spenderAddress;
213
- if (isMultiAssetVault) {
214
- spenderAddress = target;
215
- }
216
- else if (isAdapterDeposit && adapterConfig?.wrapperAddress) {
217
- spenderAddress = adapterConfig.wrapperAddress;
218
- }
219
- else {
220
- spenderAddress = target;
221
- }
341
+ const spenderAddress = resolveSpender({
342
+ target,
343
+ isMultiAssetVault,
344
+ isAdapterDeposit,
345
+ adapterWrapperAddress: adapterConfig?.wrapperAddress,
346
+ });
222
347
  const depositTokenContract = (0, core_1.createContract)({
223
348
  address: actualDepositAsset,
224
349
  provider: signer,
225
350
  abi: abis_1.ABI_ERC20,
226
351
  });
227
352
  const currentAllowance = await depositTokenContract.allowance(wallet, spenderAddress);
228
- if (safeBigInt(currentAllowance) < BigInt(normalizedAmt.raw)) {
353
+ if (safeBigInt(currentAllowance, 'vaultDeposit:allowance') <
354
+ BigInt(normalizedAmt.raw)) {
229
355
  const { hash: approveHash } = await safeSendTx(() => depositTokenContract
230
356
  .connect(signer)
231
- .approve(spenderAddress, normalizedAmt.raw), signer, wait);
357
+ .approve(spenderAddress, normalizedAmt.raw), signer, true);
232
358
  core_1.Logger.log.info('approve:tx_hash', approveHash);
233
359
  }
234
360
  }
@@ -254,7 +380,7 @@ async function vaultDeposit(signer, options) {
254
380
  srcToken: actualDepositAsset,
255
381
  srcDecimals: depositTokenDecimals,
256
382
  destToken: underlyingAsset,
257
- destDecimals: decimals,
383
+ destDecimals: vaultDecimals,
258
384
  amount: normalizedAmt.raw.toString(),
259
385
  network: chainId?.toString() || '1',
260
386
  adapterConfig,
@@ -308,8 +434,10 @@ async function vaultDeposit(signer, options) {
308
434
  core_1.Logger.log.warn('deposit:nonce-fallback', { hash: recovered });
309
435
  return recovered;
310
436
  }
437
+ if (e instanceof core_1.AugustSDKError)
438
+ throw e;
311
439
  core_1.Logger.log.error('deposit', e, { target, amount, depositAsset });
312
- throw new Error(`Deposit failed: ${e instanceof Error ? e.message : 'Unknown error'}`);
440
+ throw new core_1.AugustSDKError('UNKNOWN', `Deposit failed: ${e instanceof Error ? e.message : 'Unknown error'}`, { cause: e, context: { target, amount, depositAsset } });
313
441
  }
314
442
  }
315
443
  async function vaultRequestRedeem(signer, options) {
@@ -318,8 +446,13 @@ async function vaultRequestRedeem(signer, options) {
318
446
  (0, core_1.checkAddress)(wallet, console, 'wallet'),
319
447
  (0, core_1.checkAddress)(target, console),
320
448
  ];
321
- if (!goodWallet || !goodPool)
322
- return;
449
+ if (!goodWallet || !goodPool) {
450
+ throw new core_1.AugustValidationError('INVALID_ADDRESS', `vaultRequestRedeem: invalid ${!goodWallet ? 'wallet' : 'target'} address`);
451
+ }
452
+ if (amount === undefined || amount === null) {
453
+ throw new core_1.AugustValidationError('INVALID_INPUT', 'vaultRequestRedeem: amount is required');
454
+ }
455
+ validateAmountPrecision(amount);
323
456
  try {
324
457
  const tokenizedVault = (await (0, core_1.fetchTokenizedVault)(target))?.[0];
325
458
  const vaultVersion = (0, core_1.getVaultVersionV2)(tokenizedVault);
@@ -340,13 +473,10 @@ async function vaultRequestRedeem(signer, options) {
340
473
  decimals = Number(await receiptContract.decimals());
341
474
  const normalizedAmt = (0, core_1.toNormalizedBn)(amount, decimals);
342
475
  const allowance = await receiptContract.allowance(wallet, target);
343
- if (safeBigInt(allowance) < BigInt(normalizedAmt.raw)) {
344
- const approveTx = await receiptContract
345
- .connect(signer)
346
- .approve(target, normalizedAmt.raw);
347
- if (wait)
348
- await safeWaitForTx(approveTx);
349
- core_1.Logger.log.info('approve:receipt_token:tx_hash', approveTx?.hash);
476
+ if (safeBigInt(allowance, 'vaultRequestRedeem:allowance') <
477
+ BigInt(normalizedAmt.raw)) {
478
+ const { hash: approveHash } = await safeSendTx(() => receiptContract.connect(signer).approve(target, normalizedAmt.raw), signer, true);
479
+ core_1.Logger.log.info('approve:receipt_token:tx_hash', approveHash);
350
480
  }
351
481
  poolContract = vaultContract;
352
482
  }
@@ -399,8 +529,10 @@ async function vaultRequestRedeem(signer, options) {
399
529
  core_1.Logger.log.warn('requestRedeem:nonce-fallback', { hash: recovered });
400
530
  return recovered;
401
531
  }
532
+ if (e instanceof core_1.AugustSDKError)
533
+ throw e;
402
534
  core_1.Logger.log.error('requestRedeem', e, { target, amount });
403
- throw new Error(`Request redeem failed: ${e instanceof Error ? e.message : 'Unknown error'}`);
535
+ throw new core_1.AugustSDKError('UNKNOWN', `Request redeem failed: ${e instanceof Error ? e.message : 'Unknown error'}`, { cause: e, context: { target, amount } });
404
536
  }
405
537
  }
406
538
  async function vaultRedeem(signer, options) {
@@ -409,32 +541,46 @@ async function vaultRedeem(signer, options) {
409
541
  (0, core_1.checkAddress)(wallet, console, 'wallet'),
410
542
  (0, core_1.checkAddress)(target, console),
411
543
  ];
412
- if (!(goodWallet && goodPool && year && day && month && receiverIndex))
413
- return;
544
+ if (!goodWallet || !goodPool) {
545
+ throw new core_1.AugustValidationError('INVALID_ADDRESS', `vaultRedeem: invalid ${!goodWallet ? 'wallet' : 'target'} address`);
546
+ }
547
+ if (!year || !month || !day || !receiverIndex) {
548
+ throw new core_1.AugustValidationError('INVALID_INPUT', 'vaultRedeem: year, month, day, and receiverIndex are required');
549
+ }
414
550
  try {
415
551
  const poolContract = (0, core_1.createContract)({
416
552
  address: target,
417
553
  provider: signer,
418
554
  abi: abis_1.ABI_LENDING_POOLS,
419
555
  });
420
- const redeemTx = await poolContract
556
+ const { hash: redeemHash } = await safeSendTx(() => poolContract
421
557
  .connect(signer)
422
- .redeem(year, month, day, receiverIndex, wallet);
423
- if (wait)
424
- await safeWaitForTx(redeemTx);
425
- core_1.Logger.log.info('redeem:tx_hash', redeemTx?.hash);
426
- return redeemTx?.hash;
558
+ .redeem(year, month, day, receiverIndex, wallet), signer, wait);
559
+ core_1.Logger.log.info('redeem:tx_hash', redeemHash);
560
+ return redeemHash;
427
561
  }
428
562
  catch (e) {
563
+ const recovered = await tryRecoverTxHash(e, signer, wait);
564
+ if (recovered) {
565
+ core_1.Logger.log.warn('redeem:nonce-fallback', { hash: recovered });
566
+ return recovered;
567
+ }
568
+ if (e instanceof core_1.AugustSDKError)
569
+ throw e;
429
570
  core_1.Logger.log.error('redeem', e, { target, year, month, day, receiverIndex });
430
- throw new Error(`Redeem failed: ${e instanceof Error ? e.message : 'Unknown error'}`);
571
+ throw new core_1.AugustSDKError('UNKNOWN', `Redeem failed: ${e instanceof Error ? e.message : 'Unknown error'}`, { cause: e, context: { target, year, month, day, receiverIndex } });
431
572
  }
432
573
  }
433
574
  async function depositNative(signer, options) {
434
575
  const { wrapperAddress, receiver, amount, wait } = options;
435
576
  const goodWrapper = (0, core_1.checkAddress)(wrapperAddress, console, 'contract');
436
- if (!goodWrapper || !amount)
437
- return;
577
+ if (!goodWrapper) {
578
+ throw new core_1.AugustValidationError('INVALID_ADDRESS', 'depositNative: invalid wrapper address');
579
+ }
580
+ if (amount === undefined || amount === null) {
581
+ throw new core_1.AugustValidationError('INVALID_INPUT', 'depositNative: amount is required');
582
+ }
583
+ validateAmountPrecision(amount);
438
584
  try {
439
585
  const wrapperContract = (0, core_1.createContract)({
440
586
  address: wrapperAddress,
@@ -450,8 +596,9 @@ async function depositNative(signer, options) {
450
596
  const connectedContract = wrapperContract.connect(signer);
451
597
  if (receiver) {
452
598
  const goodReceiver = (0, core_1.checkAddress)(receiver, console, 'wallet');
453
- if (!goodReceiver)
454
- return;
599
+ if (!goodReceiver) {
600
+ throw new core_1.AugustValidationError('INVALID_ADDRESS', 'depositNative: invalid receiver address');
601
+ }
455
602
  const depositNativeWithReceiver = connectedContract.getFunction('depositNative(address)');
456
603
  depositTx = await depositNativeWithReceiver(receiver, {
457
604
  value: amountBigInt,
@@ -474,8 +621,10 @@ async function depositNative(signer, options) {
474
621
  core_1.Logger.log.warn('depositNative:nonce-fallback', { hash: recovered });
475
622
  return recovered;
476
623
  }
624
+ if (e instanceof core_1.AugustSDKError)
625
+ throw e;
477
626
  core_1.Logger.log.error('depositNative', e, { wrapperAddress, receiver, amount });
478
- throw new Error(`Deposit native failed: ${e instanceof Error ? e.message : 'Unknown error'}`);
627
+ throw new core_1.AugustSDKError('UNKNOWN', `Deposit native failed: ${e instanceof Error ? e.message : 'Unknown error'}`, { cause: e, context: { wrapperAddress, receiver, amount } });
479
628
  }
480
629
  }
481
630
  async function rwaRedeemAsset(signer, options) {
@@ -483,27 +632,38 @@ async function rwaRedeemAsset(signer, options) {
483
632
  const goodTarget = (0, core_1.checkAddress)(target, console, 'contract');
484
633
  const goodAsset = (0, core_1.checkAddress)(asset, console, 'contract');
485
634
  const goodWallet = (0, core_1.checkAddress)(wallet, console, 'wallet');
486
- if (!goodTarget || !goodAsset || !goodWallet)
487
- return;
635
+ if (!goodTarget || !goodAsset || !goodWallet) {
636
+ throw new core_1.AugustValidationError('INVALID_ADDRESS', `rwaRedeemAsset: invalid ${!goodTarget ? 'target' : !goodAsset ? 'asset' : 'wallet'} address`);
637
+ }
638
+ validateAmountPrecision(amount);
639
+ validateAmountPrecision(minOut);
488
640
  try {
489
641
  const subaccountContract = (0, core_1.createContract)({
490
642
  address: target,
491
643
  provider: signer,
492
644
  abi: abis_1.RWA_REDEEM_SUBACCOUNT,
493
645
  });
494
- if (!subaccountContract)
495
- return;
646
+ if (!subaccountContract) {
647
+ throw new Error(`rwaRedeemAsset: failed to instantiate subaccount contract at ${target}`);
648
+ }
496
649
  const normalizedAmt = (0, core_1.toNormalizedBn)(amount, decimals);
497
650
  const normalizedMinOut = (0, core_1.toNormalizedBn)(minOut, outputDecimals);
498
- const tx = await subaccountContract.redeemAsset(asset, BigInt(normalizedAmt.raw), BigInt(normalizedMinOut.raw));
499
- if (wait)
500
- await safeWaitForTx(tx);
501
- core_1.Logger.log.info('rwaRedeemAsset:tx_hash', tx?.hash);
502
- return tx?.hash;
651
+ const { hash: redeemHash } = await safeSendTx(() => subaccountContract
652
+ .connect(signer)
653
+ .redeemAsset(asset, BigInt(normalizedAmt.raw), BigInt(normalizedMinOut.raw)), signer, wait);
654
+ core_1.Logger.log.info('rwaRedeemAsset:tx_hash', redeemHash);
655
+ return redeemHash;
503
656
  }
504
657
  catch (e) {
658
+ const recovered = await tryRecoverTxHash(e, signer, wait);
659
+ if (recovered) {
660
+ core_1.Logger.log.warn('rwaRedeemAsset:nonce-fallback', { hash: recovered });
661
+ return recovered;
662
+ }
663
+ if (e instanceof core_1.AugustSDKError)
664
+ throw e;
505
665
  core_1.Logger.log.error('rwaRedeemAsset', e, { target, asset, amount, minOut });
506
- throw new Error(`RWA redeem failed: ${e instanceof Error ? e.message : 'Unknown error'}`);
666
+ throw new core_1.AugustSDKError('UNKNOWN', `RWA redeem failed: ${e instanceof Error ? e.message : 'Unknown error'}`, { cause: e, context: { target, asset, amount, minOut } });
507
667
  }
508
668
  }
509
669
  //# sourceMappingURL=write.actions.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@augustdigital/sdk",
3
- "version": "5.1.1",
3
+ "version": "7.0.0",
4
4
  "main": "lib/index.js",
5
5
  "keywords": [
6
6
  "augustdigital",
@@ -38,6 +38,7 @@
38
38
  "dependencies": {
39
39
  "@coral-xyz/anchor": "^0.31.1",
40
40
  "@sentry/browser": "^8.0.0",
41
+ "@sentry/node": "^8.0.0",
41
42
  "@solana/spl-token": "^0.4.14",
42
43
  "@solana/wallet-adapter-base": "^0.9.27",
43
44
  "@solana/web3.js": "^1.98.4",
@@ -70,10 +71,12 @@
70
71
  "test:jest": "jest",
71
72
  "test:jest:watch": "jest --watch",
72
73
  "test:jest:coverage": "jest --coverage",
74
+ "test:forknet": "node tests/forknet/run.mjs",
73
75
  "clean": "rm -rf ./lib",
74
76
  "format": "eslint . --fix",
75
77
  "lint-sdk": "lint-staged",
76
78
  "benchmark": "node benchmarks/run.js",
77
- "benchmark:ci": "node benchmarks/run.js --json benchmarks/results.json --md benchmarks/summary.md"
79
+ "benchmark:ci": "node benchmarks/run.js --json benchmarks/results.json --md benchmarks/summary.md",
80
+ "gen:version": "node scripts/update-version.js"
78
81
  }
79
82
  }