@fepvenancio/stela-sdk 0.8.1 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -258,11 +258,35 @@ var TOKENS = [
258
258
  addresses: {
259
259
  sepolia: "0x04f2345306bf8ef1c8c1445661354ef08421aa092459445a5d6b46641237e943"
260
260
  }
261
+ },
262
+ // NFT Collections (ERC721)
263
+ {
264
+ symbol: "GENESIS",
265
+ name: "Stela Genesis",
266
+ decimals: 0,
267
+ assetType: "ERC721",
268
+ addresses: {
269
+ sepolia: "0x0265ea52ffbf1b7e1a029b94fe1a2023899dd0bc02eb1f11c9b04ea90e957d28"
270
+ }
271
+ },
272
+ {
273
+ symbol: "MockNFT",
274
+ name: "Mock ERC721",
275
+ decimals: 0,
276
+ assetType: "ERC721",
277
+ addresses: {
278
+ sepolia: "0x032bfd52134ad92beae1bc5018a3748e1d1240efd627220e314c07e4c63433d5"
279
+ }
261
280
  }
262
281
  ];
263
282
  function normalizeHex(addr) {
264
283
  return "0x" + addr.replace(/^0x0*/i, "").toLowerCase();
265
284
  }
285
+ function getNFTCollections(network) {
286
+ return TOKENS.filter(
287
+ (t) => t.assetType === "ERC721" && t.addresses[network] !== void 0
288
+ );
289
+ }
266
290
  function getTokensForNetwork(network) {
267
291
  return TOKENS.filter((t) => t.addresses[network] !== void 0);
268
292
  }
@@ -288,6 +312,74 @@ function sharesToPercentage(shares, totalSupply, currentIssuedPercentage) {
288
312
  function calculateFeeShares(shares, feeBps) {
289
313
  return shares * feeBps / MAX_BPS;
290
314
  }
315
+ function divCeil(a, b) {
316
+ if (a === 0n) return 0n;
317
+ return (a + b - 1n) / b;
318
+ }
319
+ function proRataInterest(amount, elapsed, duration) {
320
+ if (amount === 0n || elapsed === 0n) return 0n;
321
+ if (elapsed >= duration) return amount;
322
+ return divCeil(amount * elapsed, duration);
323
+ }
324
+
325
+ // src/math/position.ts
326
+ var DEFAULT_DUST_BUFFER_SECONDS = 60n;
327
+ function shareProportionBps(shares, totalSupply) {
328
+ if (totalSupply === 0n) return 0n;
329
+ return shares * MAX_BPS / totalSupply;
330
+ }
331
+ function proportionalAssetValue(assetValue, shares, totalSupply) {
332
+ if (totalSupply === 0n || shares === 0n) return 0n;
333
+ return assetValue * shares / totalSupply;
334
+ }
335
+ function computePositionValue(params) {
336
+ const { shares, totalSupply, elapsed, duration } = params;
337
+ const shareBps = shareProportionBps(shares, totalSupply);
338
+ const debt = params.debtAssets.map((asset) => ({
339
+ asset,
340
+ proportionalValue: proportionalAssetValue(asset.value, shares, totalSupply)
341
+ }));
342
+ const interest = params.interestAssets.map((asset) => {
343
+ const fullInterest = proportionalAssetValue(asset.value, shares, totalSupply);
344
+ const accruedInterest = duration === 0n ? fullInterest : proRataInterest(fullInterest, elapsed, duration);
345
+ return { asset, fullInterest, accruedInterest };
346
+ });
347
+ const collateral = params.collateralAssets.map((asset) => ({
348
+ asset,
349
+ proportionalValue: proportionalAssetValue(asset.value, shares, totalSupply)
350
+ }));
351
+ return {
352
+ inscriptionId: params.inscriptionId,
353
+ shares,
354
+ totalSupply,
355
+ shareBps,
356
+ debt,
357
+ interest,
358
+ collateral,
359
+ accrued: interest,
360
+ elapsed,
361
+ duration
362
+ };
363
+ }
364
+ function accruedInterestWithBuffer(amount, elapsed, duration, bufferSeconds = DEFAULT_DUST_BUFFER_SECONDS) {
365
+ if (duration === 0n) return amount;
366
+ const bufferedElapsed = elapsed + bufferSeconds;
367
+ return proRataInterest(amount, bufferedElapsed, duration);
368
+ }
369
+ function computeSafePositionFloor(params) {
370
+ const { shares, totalSupply, elapsed, duration } = params;
371
+ const buffer = params.bufferSeconds ?? DEFAULT_DUST_BUFFER_SECONDS;
372
+ const debtFloor = params.debtAssets.map((asset) => ({
373
+ asset,
374
+ proportionalValue: proportionalAssetValue(asset.value, shares, totalSupply)
375
+ }));
376
+ const interestFloor = params.interestAssets.map((asset) => {
377
+ const fullInterest = proportionalAssetValue(asset.value, shares, totalSupply);
378
+ const safeAccrued = accruedInterestWithBuffer(fullInterest, elapsed, duration, buffer);
379
+ return { asset, proportionalValue: safeAccrued };
380
+ });
381
+ return { debtFloor, interestFloor };
382
+ }
291
383
  var SELECTORS = {
292
384
  InscriptionCreated: starknet.hash.getSelectorFromName("InscriptionCreated"),
293
385
  InscriptionSigned: starknet.hash.getSelectorFromName("InscriptionSigned"),
@@ -751,6 +843,27 @@ function getRefinanceApprovalTypedData(params) {
751
843
  }
752
844
  };
753
845
  }
846
+ function getTermsAcknowledgmentTypedData(params) {
847
+ return {
848
+ types: {
849
+ StarknetDomain: STARKNET_DOMAIN_TYPE,
850
+ TermsAcknowledgment: [
851
+ { name: "user", type: "ContractAddress" },
852
+ { name: "terms_version", type: "shortstring" },
853
+ { name: "terms_hash", type: "felt" },
854
+ { name: "agreed_at", type: "u128" }
855
+ ]
856
+ },
857
+ primaryType: "TermsAcknowledgment",
858
+ domain: { ...STELA_DOMAIN, chainId: params.chainId },
859
+ message: {
860
+ user: params.user,
861
+ terms_version: params.termsVersion,
862
+ terms_hash: params.termsHash,
863
+ agreed_at: params.agreedAt.toString()
864
+ }
865
+ };
866
+ }
754
867
 
755
868
  // src/offchain/signature.ts
756
869
  function serializeSignature(sig) {
@@ -3470,9 +3583,14 @@ function extractFieldU256(val) {
3470
3583
  }
3471
3584
  var ShareClient = class {
3472
3585
  contract;
3586
+ address;
3587
+ account;
3473
3588
  constructor(opts) {
3589
+ this.address = opts.stelaAddress;
3474
3590
  this.contract = new starknet.Contract(stela_default, opts.stelaAddress, opts.provider);
3591
+ this.account = opts.account;
3475
3592
  }
3593
+ // ── Read Methods ───────────────────────────────────────────────────
3476
3594
  /** Get share balance for an account on a specific inscription */
3477
3595
  async balanceOf(account, inscriptionId) {
3478
3596
  const result = await this.contract.call("balance_of", [account, ...toU256(inscriptionId)]);
@@ -3496,6 +3614,53 @@ var ShareClient = class {
3496
3614
  const result = await this.contract.call("is_approved_for_all", [owner, operator]);
3497
3615
  return Boolean(result[0]);
3498
3616
  }
3617
+ // ── Call Builders ──────────────────────────────────────────────────
3618
+ /**
3619
+ * Build a call to transfer shares (ERC1155 safeTransferFrom).
3620
+ * This enables secondary market trading of lending positions.
3621
+ *
3622
+ * @param from - Current share holder
3623
+ * @param to - Recipient address
3624
+ * @param inscriptionId - The inscription (token ID)
3625
+ * @param amount - Number of shares to transfer
3626
+ * @param data - Optional calldata (empty array by default)
3627
+ */
3628
+ buildTransferShares(from, to, inscriptionId, amount, data = []) {
3629
+ return {
3630
+ contractAddress: this.address,
3631
+ entrypoint: "safe_transfer_from",
3632
+ calldata: [from, to, ...toU256(inscriptionId), ...toU256(amount), String(data.length), ...data]
3633
+ };
3634
+ }
3635
+ /**
3636
+ * Build a call to approve an operator for all ERC1155 tokens.
3637
+ * Required before a marketplace contract can transfer shares on your behalf.
3638
+ *
3639
+ * @param operator - The address to approve (e.g., marketplace contract)
3640
+ * @param approved - Whether to approve or revoke
3641
+ */
3642
+ buildSetApprovalForAll(operator, approved) {
3643
+ return {
3644
+ contractAddress: this.address,
3645
+ entrypoint: "set_approval_for_all",
3646
+ calldata: [operator, approved ? "1" : "0"]
3647
+ };
3648
+ }
3649
+ // ── Execute Methods ────────────────────────────────────────────────
3650
+ /** Transfer shares to another address */
3651
+ async transferShares(from, to, inscriptionId, amount, data = []) {
3652
+ if (!this.account) throw new Error("Account required for write operations");
3653
+ const result = await this.account.execute([
3654
+ this.buildTransferShares(from, to, inscriptionId, amount, data)
3655
+ ]);
3656
+ return { transaction_hash: result.transaction_hash };
3657
+ }
3658
+ /** Approve or revoke an operator for all ERC1155 tokens */
3659
+ async setApprovalForAll(operator, approved) {
3660
+ if (!this.account) throw new Error("Account required for write operations");
3661
+ const result = await this.account.execute([this.buildSetApprovalForAll(operator, approved)]);
3662
+ return { transaction_hash: result.transaction_hash };
3663
+ }
3499
3664
  };
3500
3665
  function extractBigInt(result) {
3501
3666
  const arr = result;
@@ -3780,7 +3945,8 @@ var StelaSdk = class {
3780
3945
  });
3781
3946
  this.shares = new ShareClient({
3782
3947
  stelaAddress: this.stelaAddress,
3783
- provider: opts.provider
3948
+ provider: opts.provider,
3949
+ account: opts.account
3784
3950
  });
3785
3951
  const stelaContract = new starknet.Contract(stela_default, this.stelaAddress, opts.provider);
3786
3952
  this.locker = new LockerClient(stelaContract, opts.provider, opts.account);
@@ -3796,6 +3962,7 @@ exports.AUCTION_RESERVE_BPS = AUCTION_RESERVE_BPS;
3796
3962
  exports.ApiClient = ApiClient;
3797
3963
  exports.ApiError = ApiError;
3798
3964
  exports.CHAIN_ID = CHAIN_ID;
3965
+ exports.DEFAULT_DUST_BUFFER_SECONDS = DEFAULT_DUST_BUFFER_SECONDS;
3799
3966
  exports.EXPLORER_TX_URL = EXPLORER_TX_URL;
3800
3967
  exports.GRACE_PERIOD = GRACE_PERIOD;
3801
3968
  exports.InscriptionClient = InscriptionClient;
@@ -3809,11 +3976,15 @@ exports.StelaSdk = StelaSdk;
3809
3976
  exports.TOKENS = TOKENS;
3810
3977
  exports.VALID_STATUSES = VALID_STATUSES;
3811
3978
  exports.VIRTUAL_SHARE_OFFSET = VIRTUAL_SHARE_OFFSET;
3979
+ exports.accruedInterestWithBuffer = accruedInterestWithBuffer;
3812
3980
  exports.addressesEqual = addressesEqual;
3813
3981
  exports.calculateFeeShares = calculateFeeShares;
3982
+ exports.computePositionValue = computePositionValue;
3983
+ exports.computeSafePositionFloor = computeSafePositionFloor;
3814
3984
  exports.computeStatus = computeStatus;
3815
3985
  exports.convertToShares = convertToShares;
3816
3986
  exports.deserializeSignature = deserializeSignature;
3987
+ exports.divCeil = divCeil;
3817
3988
  exports.findTokenByAddress = findTokenByAddress;
3818
3989
  exports.formatAddress = formatAddress;
3819
3990
  exports.formatDuration = formatDuration;
@@ -3826,9 +3997,11 @@ exports.getCollectionBorrowAcceptanceTypedData = getCollectionBorrowAcceptanceTy
3826
3997
  exports.getCollectionLendOfferTypedData = getCollectionLendOfferTypedData;
3827
3998
  exports.getInscriptionOrderTypedData = getInscriptionOrderTypedData;
3828
3999
  exports.getLendOfferTypedData = getLendOfferTypedData;
4000
+ exports.getNFTCollections = getNFTCollections;
3829
4001
  exports.getRefinanceApprovalTypedData = getRefinanceApprovalTypedData;
3830
4002
  exports.getRefinanceOfferTypedData = getRefinanceOfferTypedData;
3831
4003
  exports.getRenegotiationProposalTypedData = getRenegotiationProposalTypedData;
4004
+ exports.getTermsAcknowledgmentTypedData = getTermsAcknowledgmentTypedData;
3832
4005
  exports.getTokensForNetwork = getTokensForNetwork;
3833
4006
  exports.hashAssets = hashAssets;
3834
4007
  exports.hashBatchEntries = hashBatchEntries;
@@ -3837,9 +4010,12 @@ exports.normalizeAddress = normalizeAddress;
3837
4010
  exports.parseAmount = parseAmount;
3838
4011
  exports.parseEvent = parseEvent;
3839
4012
  exports.parseEvents = parseEvents;
4013
+ exports.proRataInterest = proRataInterest;
4014
+ exports.proportionalAssetValue = proportionalAssetValue;
3840
4015
  exports.resolveNetwork = resolveNetwork;
3841
4016
  exports.scaleByPercentage = scaleByPercentage;
3842
4017
  exports.serializeSignature = serializeSignature;
4018
+ exports.shareProportionBps = shareProportionBps;
3843
4019
  exports.sharesToPercentage = sharesToPercentage;
3844
4020
  exports.toHex = toHex;
3845
4021
  exports.toU256 = toU256;