@coinlist-co/react 0.11.1-rc.209af8d → 0.11.1-rc.578d93b

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.
@@ -202,6 +202,12 @@ var InvariantError = class extends Error {
202
202
  this.name = "InvariantError";
203
203
  }
204
204
  };
205
+ var MathError = class extends Error {
206
+ constructor(message) {
207
+ super(message);
208
+ this.name = "MathError";
209
+ }
210
+ };
205
211
 
206
212
  // src/shared/api/pagination.ts
207
213
  async function fetchAllPages(fetchPage, baseParams) {
@@ -277,9 +283,25 @@ var BlockchainAmount = Object.assign(
277
283
  (value) => value,
278
284
  {
279
285
  add: (a, b) => combineAmounts(a, b, (x, y) => x + y),
280
- sub: (a, b) => combineAmounts(a, b, (x, y) => x - y)
286
+ sub: (a, b) => combineAmounts(a, b, (x, y) => x - y),
287
+ mul: multiplyAmounts,
288
+ div: divideAmounts
281
289
  }
282
290
  );
291
+ function multiplyAmounts(a, b) {
292
+ const product = a.raw * b.raw;
293
+ return BlockchainAmount({
294
+ raw: product / 10n ** BigInt(b.decimals),
295
+ decimals: a.decimals
296
+ });
297
+ }
298
+ function divideAmounts(a, b) {
299
+ if (b.raw === 0n) {
300
+ throw new MathError("Cannot divide a BlockchainAmount by zero");
301
+ }
302
+ const scaled = a.raw * 10n ** BigInt(b.decimals);
303
+ return BlockchainAmount({ raw: scaled / b.raw, decimals: a.decimals });
304
+ }
283
305
  function combineAmounts(a, b, op) {
284
306
  if (a.decimals !== b.decimals) {
285
307
  throw new InvariantError(
@@ -517,6 +539,9 @@ function classifyLogCause(error) {
517
539
  if (error instanceof InvariantError) {
518
540
  return { type: "invariant", message: error.message };
519
541
  }
542
+ if (error instanceof MathError) {
543
+ return { type: "math", message: error.message };
544
+ }
520
545
  if (error instanceof NotAuthenticatedError) {
521
546
  return { type: "not-authenticated" };
522
547
  }
@@ -1196,47 +1221,122 @@ var OndoQuote = {
1196
1221
  };
1197
1222
  }
1198
1223
  };
1199
- var OndoSwapTransaction = {
1224
+ var OndoBuyTransaction = {
1200
1225
  fromDto: (dto) => {
1201
- const inputDecimals = AssetDecimals(dto.pay_input_decimals);
1226
+ const spendDecimals = AssetDecimals(dto.spend_input_decimals);
1202
1227
  const outputDecimals = AssetDecimals(dto.receive_output_decimals);
1203
1228
  return {
1204
- tx: {
1205
- to: EvmContractAddress(dto.to),
1206
- data: HexEncodedTransactionData(dto.data)
1207
- },
1208
- expiresAt: parseExpiresAt(dto.expires_at),
1209
- payInputAmount: blockchainAmountFromRawOrThrow({
1210
- label: "pay_input_amount",
1211
- raw: dto.pay_input_amount,
1212
- decimals: inputDecimals
1213
- }),
1229
+ ...parseSwapCore(dto, spendDecimals),
1230
+ side: "buy",
1214
1231
  fee: blockchainAmountFromRawOrThrow({
1215
1232
  label: "fee",
1216
1233
  raw: dto.fee,
1217
- decimals: inputDecimals
1234
+ decimals: spendDecimals
1218
1235
  }),
1219
1236
  notionalValue: blockchainAmountFromRawOrThrow({
1220
1237
  label: "notional_value",
1221
1238
  raw: dto.notional_value,
1222
- decimals: inputDecimals
1239
+ decimals: spendDecimals
1223
1240
  }),
1224
- receiveOutputAmount: parseReceiveOutputAmount(
1225
- dto.receive_output_amount,
1226
- outputDecimals
1227
- )
1241
+ receiveOutputAmount: parsePositiveAmount({
1242
+ label: "receive_output_amount",
1243
+ raw: dto.receive_output_amount,
1244
+ decimals: outputDecimals,
1245
+ // A transaction that yields nothing is not one to sign - the user
1246
+ // would pay the deposit and receive no asset - and frontline refuses
1247
+ // to emit one. A zero here is a changed encoding, not a small order.
1248
+ // Rejecting it at the boundary is also what lets `computeOndoBuyPrice`
1249
+ // divide by it without a fallible result: the failure surfaces as the
1250
+ // data hook's ERROR state rather than as a division during render.
1251
+ reason: "a buy that yields nothing is not fillable"
1252
+ })
1228
1253
  };
1229
1254
  }
1230
1255
  };
1231
- function parseReceiveOutputAmount(raw, decimals) {
1232
- const amount = blockchainAmountFromRawOrThrow({
1233
- label: "receive_output_amount",
1256
+ var OndoSellTransaction = {
1257
+ fromDto: (dto) => {
1258
+ const spendDecimals = AssetDecimals(dto.spend_input_decimals);
1259
+ const outputDecimals = AssetDecimals(dto.receive_output_decimals);
1260
+ const expectedQuantity = parsePositiveAmount({
1261
+ label: "expected_quantity",
1262
+ raw: dto.expected_quantity,
1263
+ decimals: outputDecimals,
1264
+ reason: "a sale that yields nothing is not fillable"
1265
+ });
1266
+ return {
1267
+ ...parseSwapCore(dto, spendDecimals),
1268
+ side: "sell",
1269
+ expected: {
1270
+ quantity: expectedQuantity,
1271
+ fee: blockchainAmountFromRawOrThrow({
1272
+ label: "expected_fee",
1273
+ raw: dto.expected_fee,
1274
+ decimals: outputDecimals
1275
+ })
1276
+ },
1277
+ minimum: {
1278
+ quantity: parseMinimumQuantity(
1279
+ dto.minimum_quantity,
1280
+ outputDecimals,
1281
+ expectedQuantity
1282
+ ),
1283
+ fee: blockchainAmountFromRawOrThrow({
1284
+ label: "minimum_fee",
1285
+ raw: dto.minimum_fee,
1286
+ decimals: outputDecimals
1287
+ })
1288
+ }
1289
+ };
1290
+ }
1291
+ };
1292
+ function parseSwapCore(dto, spendDecimals) {
1293
+ return {
1294
+ tx: {
1295
+ to: EvmContractAddress(dto.to),
1296
+ data: HexEncodedTransactionData(dto.data)
1297
+ },
1298
+ expiresAt: parseExpiresAt(dto.expires_at),
1299
+ spendInputAmount: parsePositiveAmount({
1300
+ label: "spend_input_amount",
1301
+ raw: dto.spend_input_amount,
1302
+ decimals: spendDecimals,
1303
+ // A transaction that takes nothing from the wallet is not one to sign:
1304
+ // it would settle one leg of a trade and skip the other. Frontline
1305
+ // refuses an `amount` of zero whichever way the trade runs, so this is a
1306
+ // changed encoding rather than a small order.
1307
+ //
1308
+ // Guarded on both sides rather than on the sale alone, because which
1309
+ // amount becomes the divisor in the price flips with the direction: a
1310
+ // guard placed by that would be a rule about the arithmetic rather than
1311
+ // about the trade.
1312
+ reason: "a swap that spends nothing is not fillable"
1313
+ })
1314
+ };
1315
+ }
1316
+ function parseMinimumQuantity(raw, decimals, expectedQuantity) {
1317
+ const amount = parsePositiveAmount({
1318
+ label: "minimum_quantity",
1234
1319
  raw,
1235
- decimals
1320
+ decimals,
1321
+ reason: "a floor of zero guarantees nothing"
1236
1322
  });
1323
+ if (amount.raw > expectedQuantity.raw) {
1324
+ throw new ValidationError(
1325
+ `minimum_quantity: must not exceed expected_quantity ("${raw}" > "${expectedQuantity.raw}")`
1326
+ );
1327
+ }
1328
+ return amount;
1329
+ }
1330
+ function parsePositiveAmount({
1331
+ label,
1332
+ raw,
1333
+ decimals,
1334
+ reason
1335
+ }) {
1336
+ const amount = blockchainAmountFromRawOrThrow({ label, raw, decimals });
1237
1337
  if (amount.raw <= 0n) {
1238
1338
  throw new ValidationError(
1239
- `receive_output_amount: must be greater than zero ("${raw}")`
1339
+ `${label}: must be greater than zero ("${raw}") - ${reason}`
1240
1340
  );
1241
1341
  }
1242
1342
  return amount;
@@ -1273,27 +1373,57 @@ async function getOndoQuote(api, params) {
1273
1373
  });
1274
1374
  return OndoQuote.fromDto(dto);
1275
1375
  }
1276
- async function buildOndoSwapTransaction(api, params) {
1376
+ async function buildOndoBuy(api, params) {
1277
1377
  const dto = await api.send({
1278
1378
  method: "POST",
1279
- url: "/v1/ondo/swap/transaction",
1280
- body: {
1281
- symbol: params.symbol,
1282
- chain: params.chain,
1283
- wallet_address: params.walletAddress,
1284
- amount: params.amount.raw.toString()
1285
- },
1379
+ url: "/v1/ondo/swap/buy",
1380
+ body: swapBody(params),
1286
1381
  attributes: Attributes.protected()
1287
1382
  });
1288
- assertFundingScaleAgrees(dto, params);
1289
- return OndoSwapTransaction.fromDto(dto);
1383
+ assertSpendScaleAgrees({
1384
+ published: dto.spend_input_decimals,
1385
+ sized: params.amount,
1386
+ trade: "purchase"
1387
+ });
1388
+ return OndoBuyTransaction.fromDto(dto);
1290
1389
  }
1291
- function assertFundingScaleAgrees(dto, params) {
1292
- if (dto.pay_input_decimals !== params.amount.decimals) {
1293
- throw new ValidationError(
1294
- `pay_input_decimals: the swap was priced in ${dto.pay_input_decimals} decimals but the order was sized in ${params.amount.decimals}`
1295
- );
1296
- }
1390
+ async function buildOndoSell(api, params) {
1391
+ const dto = await api.send({
1392
+ method: "POST",
1393
+ url: "/v1/ondo/swap/sell",
1394
+ body: swapBody(params),
1395
+ attributes: Attributes.protected()
1396
+ });
1397
+ assertSpendScaleAgrees({
1398
+ published: dto.spend_input_decimals,
1399
+ sized: params.amount,
1400
+ trade: "sale",
1401
+ // The two answers come from two chains, so on a testnet they can disagree
1402
+ // for a reason that is neither the caller's nor a corrupt response. Say so,
1403
+ // or a QA run reads as a puzzle rather than a diagnosis.
1404
+ note: "the quote resolves the asset on Ethereum mainnet while the swap executes on the chain requested, so these disagree until frontline serves a chain-scoped quote"
1405
+ });
1406
+ return OndoSellTransaction.fromDto(dto);
1407
+ }
1408
+ function swapBody(params) {
1409
+ return {
1410
+ symbol: params.symbol,
1411
+ chain: params.chain,
1412
+ wallet_address: params.walletAddress,
1413
+ amount: params.amount.raw.toString()
1414
+ };
1415
+ }
1416
+ function assertSpendScaleAgrees({
1417
+ published,
1418
+ sized,
1419
+ trade,
1420
+ note
1421
+ }) {
1422
+ if (published === sized.decimals) return;
1423
+ const because = note === void 0 ? "" : ` - ${note}`;
1424
+ throw new ValidationError(
1425
+ `spend_input_decimals: the ${trade} was priced in ${published} decimals but the order was sized in ${sized.decimals}${because}`
1426
+ );
1297
1427
  }
1298
1428
  function sizeParam(params) {
1299
1429
  const tokenAmount = "tokenAmount" in params ? params.tokenAmount : void 0;
@@ -1332,10 +1462,16 @@ var OndoNamespaceImpl = class {
1332
1462
  return getOndoQuote(this.ctx.api, params);
1333
1463
  });
1334
1464
  }
1335
- async buildSwapTransaction(params) {
1336
- return this.log.wrap("buildSwapTransaction", params, async () => {
1465
+ async buildBuyTransaction(params) {
1466
+ return this.log.wrap("buildBuyTransaction", params, async () => {
1467
+ await this.ctx.ensureUserAuthenticated();
1468
+ return buildOndoBuy(this.ctx.api, params);
1469
+ });
1470
+ }
1471
+ async buildSellTransaction(params) {
1472
+ return this.log.wrap("buildSellTransaction", params, async () => {
1337
1473
  await this.ctx.ensureUserAuthenticated();
1338
- return buildOndoSwapTransaction(this.ctx.api, params);
1474
+ return buildOndoSell(this.ctx.api, params);
1339
1475
  });
1340
1476
  }
1341
1477
  };
@@ -2135,6 +2271,7 @@ export {
2135
2271
  NotAuthenticatedError,
2136
2272
  ValidationError,
2137
2273
  InvariantError,
2274
+ MathError,
2138
2275
  describeErrorUnredacted,
2139
2276
  internalLogger,
2140
2277
  HttpClient,
@@ -2215,7 +2352,8 @@ export {
2215
2352
  Ticker,
2216
2353
  OndoTradingStatus,
2217
2354
  OndoQuote,
2218
- OndoSwapTransaction,
2355
+ OndoBuyTransaction,
2356
+ OndoSellTransaction,
2219
2357
  OndoNamespaceImpl,
2220
2358
  SuperstateSwapNamespaceImpl,
2221
2359
  fetchOffers,
@@ -2246,4 +2384,4 @@ export {
2246
2384
  OAuthRefreshToken,
2247
2385
  OAuthSession
2248
2386
  };
2249
- //# sourceMappingURL=chunk-3Z4PLLV7.js.map
2387
+ //# sourceMappingURL=chunk-HYC4JARU.js.map