@scallop-io/scallop-deepbook-kit 0.2.1 → 0.4.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 +1 -1
- package/dist/index.d.cts +7 -2
- package/dist/index.d.ts +7 -2
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/src/examples/margin-pool-demo.ts +15 -6
- package/src/index.ts +1 -0
- package/src/queries/getOnChainMarginPools.ts +61 -0
- package/src/queries/index.ts +1 -0
- package/src/toolkit/DeepBookMarginPool.ts +135 -5
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
'use strict';var client=require('@mysten/sui/client'),ed25519=require('@mysten/sui/keypairs/ed25519'),transactions=require('@mysten/sui/transactions'),deepbookV3=require('@mysten/deepbook-v3'),cryptography=require('@mysten/sui/cryptography'),bcs$1=require('@mysten/bcs'),bcs=require('@mysten/sui/bcs'),bignumber_js=require('bignumber.js');var T=n=>/^0x[0-9a-fA-F]+$|^[0-9a-fA-F]+$/.test(n),B=n=>/^[a-zA-Z0-9+/]+={0,2}$/g.test(n),A=n=>{if(T(n))return bcs$1.fromHex(n);if(B(n))return bcs$1.fromBase64(n);throw new Error("The string is not a valid hex or base64 string.")},P=n=>{if(n.length===cryptography.LEGACY_PRIVATE_KEY_SIZE)return n.slice(0,cryptography.PRIVATE_KEY_SIZE);if(n.length===cryptography.PRIVATE_KEY_SIZE+1&&n[0]===0)return n.slice(1);if(n.length===cryptography.PRIVATE_KEY_SIZE)return n;throw new Error("invalid secret key")};var C=class{suiClient;keypair;address;marginPoolContract;supplierCapId;dbConfig;supplierCapPackageId;constructor({network:r,fullnodeUrl:i,supplierCapId:t,privateKey:e,supplierCapPackageId:o,dbConfig:a}){let s=i??client.getFullnodeUrl(r);this.suiClient=new client.SuiClient({url:s}),this.keypair=this.#r(e),this.address=this.keypair.getPublicKey().toSuiAddress(),this.supplierCapId=t,this.dbConfig=a??new deepbookV3.DeepBookConfig({network:r,address:this.address}),this.marginPoolContract=new deepbookV3.MarginPoolContract(this.dbConfig),this.supplierCapPackageId=o??this.dbConfig.MARGIN_PACKAGE_ID;}#r(r){if(r.startsWith(cryptography.SUI_PRIVATE_KEY_PREFIX)){let{secretKey:i}=cryptography.decodeSuiPrivateKey(r);return ed25519.Ed25519Keypair.fromSecretKey(P(i))}return ed25519.Ed25519Keypair.fromSecretKey(P(A(r)))}async#t(){let r=`${this.dbConfig.MARGIN_PACKAGE_ID}::margin_pool::SupplierCap`;return (await this.suiClient.getOwnedObjects({owner:this.address,filter:{StructType:r},options:{showType:true}})).data?.[0]?.data?.objectId}async initialize(){if(this.supplierCapId)return this.supplierCapId;let r=await this.#t();if(r)return this.supplierCapId=r,r;let i=await this.createSupplierCap();if(!i)throw new Error("Failed to create Supplier Cap");return this.supplierCapId=i,i}async createSupplierCap(){try{let r=new transactions.Transaction;r.setSender(this.address);let i=r.moveCall({target:`${this.supplierCapPackageId}::margin_pool::mint_supplier_cap`,arguments:[r.object(this.dbConfig.MARGIN_REGISTRY_ID),r.object.clock()]});r.transferObjects([i],r.pure.address(this.address));let t=await this.suiClient.signAndExecuteTransaction({signer:this.keypair,transaction:r,options:{showEffects:!0,showObjectChanges:!0}});if(t.errors&&t.errors.length>0)throw new Error(`Transaction failed with errors: ${t.errors.map(e=>e.toString()).join(", ")}`);if(t.objectChanges){for(let e of t.objectChanges)if(e.type==="created"&&e.objectType.includes("SupplierCap"))return e.objectId}return null}catch(r){throw new Error(`Failed to create Supplier Cap: ${r.message||r}`)}}async createSupplyReferral(r){try{let i=new transactions.Transaction;i.setSender(this.address);let t=this.dbConfig.getMarginPool(r);if(!t)throw new Error(`Margin pool configuration not found for coin: ${r}`);i.moveCall({target:`${this.dbConfig.MARGIN_PACKAGE_ID}::margin_pool::mint_supply_referral`,arguments:[i.object(t.address),i.object(this.dbConfig.MARGIN_REGISTRY_ID),i.object.clock()],typeArguments:[t.type]});let e=await this.suiClient.signAndExecuteTransaction({signer:this.keypair,transaction:i,options:{showEffects:!0,showObjectChanges:!0}});if(e.errors&&e.errors.length>0)throw new Error(`Transaction failed with errors: ${e.errors.map(o=>o.toString()).join(", ")}`);if(e.objectChanges){for(let o of e.objectChanges)if(o.type==="created"&&o.objectType.includes("SupplyReferral"))return o.objectId}return null}catch(i){throw new Error(`Failed to create Supply Referral: ${i.message||i}`)}}async supplyToMarginPool(r,i,t){try{if(!this.supplierCapId)throw new Error("Supplier Cap not initialized. Call initialize() first.");let e=new transactions.Transaction;e.setSender(this.address);let o=e.object(this.supplierCapId);e.add(this.marginPoolContract.supplyToMarginPool(r,o,i,t));let{errors:a}=await this.suiClient.signAndExecuteTransaction({signer:this.keypair,transaction:e,options:{showEffects:!0,showObjectChanges:!0}});if(a&&a.length>0)throw new Error(`Transaction failed with errors: ${a.map(s=>s.toString()).join(", ")}`);return !0}catch(e){throw new Error(`Failed to supply to margin pool: ${e.message||e}`)}}async withdrawFromMarginPool(r,i){try{if(!this.supplierCapId)throw new Error("Supplier Cap not initialized. Call initialize() first.");let t=new transactions.Transaction,e=t.object(this.supplierCapId),a=this.marginPoolContract.withdrawFromMarginPool(r,e,i)(t);t.transferObjects([a],this.address);let{errors:s}=await this.suiClient.signAndExecuteTransaction({signer:this.keypair,transaction:t,options:{showEffects:!0,showObjectChanges:!0}});if(s&&s.length>0)throw new Error(`Transaction failed with errors: ${s.map(p=>p.toString()).join(", ")}`);return !0}catch(t){throw new Error(`Failed to withdraw from margin pool: ${t.message||t}`)}}async withdrawReferralFees(r,i){try{let t=new transactions.Transaction;t.add(this.marginPoolContract.withdrawReferralFees(r,i));let{errors:e}=await this.suiClient.signAndExecuteTransaction({signer:this.keypair,transaction:t,options:{showEffects:!0,showObjectChanges:!0,showBalanceChanges:!0}});if(e&&e.length>0)throw new Error(`Transaction failed with errors: ${e.map(o=>o.toString()).join(", ")}`);return !0}catch(t){throw new Error(`Failed to withdraw referral fees: ${t.message||t}`)}}async getBalance(r){try{if(!this.supplierCapId)throw new Error("Supplier Cap not initialized. Call initialize() first.");let i=new transactions.Transaction;i.add(this.marginPoolContract.userSupplyAmount(r,this.supplierCapId));let t=await this.suiClient.devInspectTransactionBlock({sender:this.address,transactionBlock:i}),e=0;if(t&&t.results&&t.results[0]&&t.results[0].returnValues){let l=t.results[0].returnValues[0];if(l&&l[0]){let c=Buffer.from(l[0]).readBigUInt64LE(),m=this.dbConfig.getCoin(r).scalar;e=Number(c)/m;}}let o=this.dbConfig.getCoin(r).type,a=await this.suiClient.getBalance({owner:this.address,coinType:o}),s=this.dbConfig.getCoin(r).scalar,p=Number(a.totalBalance)/s;return {userSupplyAmount:e,walletBalance:p}}catch(i){throw new Error(`Failed to get balance: ${i.message||i}`)}}getSupplierCapId(){return this.supplierCapId}getAddress(){return this.address}};var w=["supplyCap","maxUtilizationRate","protocolSpread","minBorrow","interestRate","totalSupply","supplyShares","totalBorrow","borrowShares","lastUpdateTimestamp"],h=["userSupplyShares","userSupplyAmount"],_={supplyCap:"U64",maxUtilizationRate:"U64",protocolSpread:"U64",minBorrow:"U64",interestRate:"U64",totalSupply:"U64",supplyShares:"U64",totalBorrow:"U64",borrowShares:"U64",lastUpdateTimestamp:"U64",userSupplyShares:"U64",userSupplyAmount:"U64"};var d=(n,r)=>n*r/BigInt(deepbookV3.FLOAT_SCALAR),u=n=>Number(n)/deepbookV3.FLOAT_SCALAR;var W=new Set(h),D=n=>W.has(n),b=class{marginPoolContract;dbConfig;suiClient;constructor({network:r,address:i="",suiClient:t,dbConfig:e}={}){let o=r??e?.network??"mainnet";if(this.dbConfig=e??new deepbookV3.DeepBookConfig({network:o,address:i}),this.suiClient=t??new client.SuiClient({url:client.getFullnodeUrl(o)}),this.marginPoolContract=new deepbookV3.MarginPoolContract(this.dbConfig),r!==void 0&&e!==void 0&&r!==e.network)throw new Error(`Mismatch between provided network (${r}) and dbConfig network (${e.network}).`)}get network(){return this.dbConfig.network}#r(r,i,t,e){if(D(i)){let o=this.marginPoolContract[i];if(e==null)throw new Error(`supplierCap is required for '${i}'.`);r.add(o(t,e));}else {let o=this.marginPoolContract[i];r.add(o(t));}}parseInspectResultToBcsStructs(r,i){let t=r.results;if(!t)throw new Error("No results found in DevInspect output.");return i.reduce((e,o,a)=>{let s=t[a]?.returnValues?.[0]?.[0];if(!s)return e;let p=bcs.bcs[_[o]];return e[o]=p.parse(new Uint8Array(s)),e},{})}formatResult(r,i){let t=this.dbConfig.getCoin(i),e={supplyCap:0,maxUtilizationRate:0,protocolSpread:0,minBorrow:0,interestRate:0,totalSupply:0,supplyShares:0,totalBorrow:0,borrowShares:0,lastUpdateTimestamp:0,userSupplyShares:0,userSupplyAmount:0,decimals:t.scalar.toString().length-1,highKink:0,baseBorrowApr:0,borrowAprOnHighKink:0,maxBorrowApr:0,supplyApr:0,utilizationRate:0,...t};if(!t)return e;let o=new Set(["interestRate","maxUtilizationRate","protocolSpread"]);for(let[a,s]of Object.entries(r))a==="lastUpdateTimestamp"?e[a]=Number(s):o.has(a)?e[a]=new bignumber_js.BigNumber(s).dividedBy(deepbookV3.FLOAT_SCALAR).toNumber():e[a]=new bignumber_js.BigNumber(s).dividedBy(t.scalar).toNumber();return e}computeBorrowAprAtUtil(r,i){let t=BigInt(i.base_rate),e=BigInt(i.base_slope),o=BigInt(i.excess_slope),a=BigInt(i.optimal_utilization);return r<a?t+d(r,e):t+d(a,e)+d(r-a,o)}calculateKinksAndRate(r,i,t,e){let o=BigInt(r.optimal_utilization),a=BigInt(i.max_utilization_rate),s=this.computeBorrowAprAtUtil(o,r),p=this.computeBorrowAprAtUtil(a,r),l=BigInt(bignumber_js.BigNumber(t.total_borrow).dividedBy(t.total_supply).shiftedBy(9).decimalPlaces(0).toString()),c=d(d(e,l),BigInt(deepbookV3.FLOAT_SCALAR)-BigInt(i.protocol_spread));return {raw:{baseBorrowApr:r.base_rate,highKink:o,borrowAprOnHighKink:s,maxBorrowApr:p,supplyApr:c,utilizationRate:l},normalized:{baseBorrowApr:u(BigInt(r.base_rate)),highKink:u(o),borrowAprOnHighKink:u(s),maxBorrowApr:u(p),supplyApr:u(c),utilizationRate:u(l)}}}async#t(r,i){let{address:t}=this.dbConfig.getMarginPool(r),o=((await this.suiClient.getObject({id:t,options:{showContent:true}})).data?.content).fields,a=o.config.fields,s=a.interest_config.fields,p=a.margin_pool_config.fields,l=o.state.fields,{normalized:c}=this.calculateKinksAndRate(s,p,l,i);return c}async getPoolParameters(r,i,t=new transactions.Transaction,e=true){if(w.forEach(m=>this.#r(t,m,r)),i&&h.forEach(m=>this.#r(t,m,r,i)),!e)return t;let o=[...w,...h],a=await this.suiClient.devInspectTransactionBlock({transactionBlock:t,sender:this.dbConfig.address}),s=this.parseInspectResultToBcsStructs(a,o),p=this.formatResult(s,r),l=BigInt(s.interestRate??0),c=await this.#t(r,l);return {...p,...c}}};exports.DeepBookMarginPool=b;exports.DeepBookMarginToolkit=C;
|
|
1
|
+
'use strict';var client=require('@mysten/sui/client'),ed25519=require('@mysten/sui/keypairs/ed25519'),transactions=require('@mysten/sui/transactions'),deepbookV3=require('@mysten/deepbook-v3'),cryptography=require('@mysten/sui/cryptography'),bcs$1=require('@mysten/bcs'),bcs=require('@mysten/sui/bcs'),bignumber_js=require('bignumber.js'),utils=require('@mysten/sui/utils');var H=s=>/^0x[0-9a-fA-F]+$|^[0-9a-fA-F]+$/.test(s),V=s=>/^[a-zA-Z0-9+/]+={0,2}$/g.test(s),B=s=>{if(H(s))return bcs$1.fromHex(s);if(V(s))return bcs$1.fromBase64(s);throw new Error("The string is not a valid hex or base64 string.")},S=s=>{if(s.length===cryptography.LEGACY_PRIVATE_KEY_SIZE)return s.slice(0,cryptography.PRIVATE_KEY_SIZE);if(s.length===cryptography.PRIVATE_KEY_SIZE+1&&s[0]===0)return s.slice(1);if(s.length===cryptography.PRIVATE_KEY_SIZE)return s;throw new Error("invalid secret key")};var A=class{suiClient;keypair;address;marginPoolContract;supplierCapId;dbConfig;supplierCapPackageId;constructor({network:r,fullnodeUrl:e,supplierCapId:t,privateKey:o,supplierCapPackageId:i,dbConfig:n}){let a=e??client.getFullnodeUrl(r);this.suiClient=new client.SuiClient({url:a}),this.keypair=this.#r(o),this.address=this.keypair.getPublicKey().toSuiAddress(),this.supplierCapId=t,this.dbConfig=n??new deepbookV3.DeepBookConfig({network:r,address:this.address}),this.marginPoolContract=new deepbookV3.MarginPoolContract(this.dbConfig),this.supplierCapPackageId=i??this.dbConfig.MARGIN_PACKAGE_ID;}#r(r){if(r.startsWith(cryptography.SUI_PRIVATE_KEY_PREFIX)){let{secretKey:e}=cryptography.decodeSuiPrivateKey(r);return ed25519.Ed25519Keypair.fromSecretKey(S(e))}return ed25519.Ed25519Keypair.fromSecretKey(S(B(r)))}async#t(){let r=`${this.dbConfig.MARGIN_PACKAGE_ID}::margin_pool::SupplierCap`;return (await this.suiClient.getOwnedObjects({owner:this.address,filter:{StructType:r},options:{showType:true}})).data?.[0]?.data?.objectId}async initialize(){if(this.supplierCapId)return this.supplierCapId;let r=await this.#t();if(r)return this.supplierCapId=r,r;let e=await this.createSupplierCap();if(!e)throw new Error("Failed to create Supplier Cap");return this.supplierCapId=e,e}async createSupplierCap(){try{let r=new transactions.Transaction;r.setSender(this.address);let e=r.moveCall({target:`${this.supplierCapPackageId}::margin_pool::mint_supplier_cap`,arguments:[r.object(this.dbConfig.MARGIN_REGISTRY_ID),r.object.clock()]});r.transferObjects([e],r.pure.address(this.address));let t=await this.suiClient.signAndExecuteTransaction({signer:this.keypair,transaction:r,options:{showEffects:!0,showObjectChanges:!0}});if(t.errors&&t.errors.length>0)throw new Error(`Transaction failed with errors: ${t.errors.map(o=>o.toString()).join(", ")}`);if(t.objectChanges){for(let o of t.objectChanges)if(o.type==="created"&&o.objectType.includes("SupplierCap"))return o.objectId}return null}catch(r){throw new Error(`Failed to create Supplier Cap: ${r.message||r}`)}}async createSupplyReferral(r){try{let e=new transactions.Transaction;e.setSender(this.address);let t=this.dbConfig.getMarginPool(r);if(!t)throw new Error(`Margin pool configuration not found for coin: ${r}`);e.moveCall({target:`${this.dbConfig.MARGIN_PACKAGE_ID}::margin_pool::mint_supply_referral`,arguments:[e.object(t.address),e.object(this.dbConfig.MARGIN_REGISTRY_ID),e.object.clock()],typeArguments:[t.type]});let o=await this.suiClient.signAndExecuteTransaction({signer:this.keypair,transaction:e,options:{showEffects:!0,showObjectChanges:!0}});if(o.errors&&o.errors.length>0)throw new Error(`Transaction failed with errors: ${o.errors.map(i=>i.toString()).join(", ")}`);if(o.objectChanges){for(let i of o.objectChanges)if(i.type==="created"&&i.objectType.includes("SupplyReferral"))return i.objectId}return null}catch(e){throw new Error(`Failed to create Supply Referral: ${e.message||e}`)}}async supplyToMarginPool(r,e,t){try{if(!this.supplierCapId)throw new Error("Supplier Cap not initialized. Call initialize() first.");let o=new transactions.Transaction;o.setSender(this.address);let i=o.object(this.supplierCapId);o.add(this.marginPoolContract.supplyToMarginPool(r,i,e,t));let{errors:n}=await this.suiClient.signAndExecuteTransaction({signer:this.keypair,transaction:o,options:{showEffects:!0,showObjectChanges:!0}});if(n&&n.length>0)throw new Error(`Transaction failed with errors: ${n.map(a=>a.toString()).join(", ")}`);return !0}catch(o){throw new Error(`Failed to supply to margin pool: ${o.message||o}`)}}async withdrawFromMarginPool(r,e){try{if(!this.supplierCapId)throw new Error("Supplier Cap not initialized. Call initialize() first.");let t=new transactions.Transaction,o=t.object(this.supplierCapId),n=this.marginPoolContract.withdrawFromMarginPool(r,o,e)(t);t.transferObjects([n],this.address);let{errors:a}=await this.suiClient.signAndExecuteTransaction({signer:this.keypair,transaction:t,options:{showEffects:!0,showObjectChanges:!0}});if(a&&a.length>0)throw new Error(`Transaction failed with errors: ${a.map(l=>l.toString()).join(", ")}`);return !0}catch(t){throw new Error(`Failed to withdraw from margin pool: ${t.message||t}`)}}async withdrawReferralFees(r,e){try{let t=new transactions.Transaction;t.add(this.marginPoolContract.withdrawReferralFees(r,e));let{errors:o}=await this.suiClient.signAndExecuteTransaction({signer:this.keypair,transaction:t,options:{showEffects:!0,showObjectChanges:!0,showBalanceChanges:!0}});if(o&&o.length>0)throw new Error(`Transaction failed with errors: ${o.map(i=>i.toString()).join(", ")}`);return !0}catch(t){throw new Error(`Failed to withdraw referral fees: ${t.message||t}`)}}async getBalance(r){try{if(!this.supplierCapId)throw new Error("Supplier Cap not initialized. Call initialize() first.");let e=new transactions.Transaction;e.add(this.marginPoolContract.userSupplyAmount(r,this.supplierCapId));let t=await this.suiClient.devInspectTransactionBlock({sender:this.address,transactionBlock:e}),o=0;if(t&&t.results&&t.results[0]&&t.results[0].returnValues){let p=t.results[0].returnValues[0];if(p&&p[0]){let u=Buffer.from(p[0]).readBigUInt64LE(),g=this.dbConfig.getCoin(r).scalar;o=Number(u)/g;}}let i=this.dbConfig.getCoin(r).type,n=await this.suiClient.getBalance({owner:this.address,coinType:i}),a=this.dbConfig.getCoin(r).scalar,l=Number(n.totalBalance)/a;return {userSupplyAmount:o,walletBalance:l}}catch(e){throw new Error(`Failed to get balance: ${e.message||e}`)}}getSupplierCapId(){return this.supplierCapId}getAddress(){return this.address}};var C=["supplyCap","maxUtilizationRate","protocolSpread","minBorrow","interestRate","totalSupply","supplyShares","totalBorrow","borrowShares","lastUpdateTimestamp"],f=["userSupplyShares","userSupplyAmount"],_={supplyCap:"U64",maxUtilizationRate:"U64",protocolSpread:"U64",minBorrow:"U64",interestRate:"U64",totalSupply:"U64",supplyShares:"U64",totalBorrow:"U64",borrowShares:"U64",lastUpdateTimestamp:"U64",userSupplyShares:"U64",userSupplyAmount:"U64"};var P=(s,r)=>s*r/BigInt(deepbookV3.FLOAT_SCALAR),d=s=>Number(s)/deepbookV3.FLOAT_SCALAR;var nr=new Set(f),ar=s=>nr.has(s),R=class{marginPoolContract;dbConfig;suiClient;constructor({network:r,address:e="",suiClient:t,dbConfig:o}={}){let i=r??o?.network??"mainnet";if(this.dbConfig=o??new deepbookV3.DeepBookConfig({network:i,address:e}),this.suiClient=t??new client.SuiClient({url:client.getFullnodeUrl(i)}),this.marginPoolContract=new deepbookV3.MarginPoolContract(this.dbConfig),r!==void 0&&o!==void 0&&r!==o.network)throw new Error(`Mismatch between provided network (${r}) and dbConfig network (${o.network}).`)}get network(){return this.dbConfig.network}#r(r,e,t,o){if(ar(e)){let i=this.marginPoolContract[e];if(o==null)throw new Error(`supplierCap is required for '${e}'.`);r.add(i(t,o));}else {let i=this.marginPoolContract[e];r.add(i(t));}}parseInspectResultToBcsStructs(r,e){let t=r.results;if(!t)throw new Error("No results found in DevInspect output.");return e.reduce((o,i,n)=>{let a=t[n]?.returnValues?.[0]?.[0];if(!a)return o;let l=bcs.bcs[_[i]];return o[i]=l.parse(new Uint8Array(a)),o},{})}formatResult(r,e){let t=this.dbConfig.getCoin(e),o={supplyCap:0,maxUtilizationRate:0,protocolSpread:0,minBorrow:0,interestRate:0,totalSupply:0,supplyShares:0,totalBorrow:0,borrowShares:0,lastUpdateTimestamp:0,userSupplyShares:0,userSupplyAmount:0,decimals:t.scalar.toString().length-1,highKink:0,baseBorrowApr:0,borrowAprOnHighKink:0,maxBorrowApr:0,supplyApr:0,utilizationRate:0,...t};if(!t)return o;let i=new Set(["interestRate","maxUtilizationRate","protocolSpread"]);for(let[n,a]of Object.entries(r))n==="lastUpdateTimestamp"?o[n]=Number(a):i.has(n)?o[n]=new bignumber_js.BigNumber(a).dividedBy(deepbookV3.FLOAT_SCALAR).toNumber():o[n]=new bignumber_js.BigNumber(a).dividedBy(t.scalar).toNumber();return o}computeBorrowAprAtUtil(r,e){let t=BigInt(e.base_rate),o=BigInt(e.base_slope),i=BigInt(e.excess_slope),n=BigInt(e.optimal_utilization);return r<n?t+P(r,o):t+P(n,o)+P(r-n,i)}calculateKinksAndRate(r,e,t,o){let i=BigInt(r.optimal_utilization),n=BigInt(e.max_utilization_rate),a=this.computeBorrowAprAtUtil(i,r),l=this.computeBorrowAprAtUtil(n,r),p=BigInt(bignumber_js.BigNumber(t.total_borrow).dividedBy(t.total_supply).shiftedBy(9).decimalPlaces(0).toString()),u=P(P(o,p),BigInt(deepbookV3.FLOAT_SCALAR)-BigInt(e.protocol_spread));return {raw:{baseBorrowApr:r.base_rate,highKink:i,borrowAprOnHighKink:a,maxBorrowApr:l,supplyApr:u,utilizationRate:p},normalized:{baseBorrowApr:d(BigInt(r.base_rate)),highKink:d(i),borrowAprOnHighKink:d(a),maxBorrowApr:d(l),supplyApr:d(u),utilizationRate:d(p)}}}async#t(r,e,t){let{address:o}=this.dbConfig.getMarginPool(r);t??=await this.suiClient.getObject({id:o,options:{showContent:true}});let i=(t.data?.content).fields,n=i.config.fields,a=n.interest_config.fields,l=n.margin_pool_config.fields,p=i.state.fields,{normalized:u}=this.calculateKinksAndRate(a,l,p,e);return u}async getPoolParameters(r,e,t=new transactions.Transaction,o=true){if(C.forEach(g=>this.#r(t,g,r)),e&&f.forEach(g=>this.#r(t,g,r,e)),!o)return t;let i=[...C,...f],n=await this.suiClient.devInspectTransactionBlock({transactionBlock:t,sender:this.dbConfig.address}),a=this.parseInspectResultToBcsStructs(n,i),l=this.formatResult(a,r),p=BigInt(a.interestRate??0),u=await this.#t(r,p);return {...l,...u}}async getPoolsParameters(r,e,t=new transactions.Transaction,o=true){for(let c of r)C.forEach(m=>this.#r(t,m,c)),e&&f.forEach(m=>this.#r(t,m,c,e));if(!o)return t;let i=[...C,...e?f:[]],n=i.length,a=r.map(c=>this.dbConfig.getMarginPool(c).address),l=50,p=[];for(let c=0;c<a.length;c+=l)p.push(a.slice(c,c+l));let[u,...g]=await Promise.all([this.suiClient.devInspectTransactionBlock({transactionBlock:t,sender:this.dbConfig.address}),...p.map(c=>this.suiClient.multiGetObjects({ids:c,options:{showContent:true}}))]),v=g.flat(),I=u.results;if(!I)throw new Error("No results found in DevInspect output.");return Promise.all(r.map(async(c,m)=>{let N=m*n,T=i.reduce((y,E,L)=>{let K=I[N+L]?.returnValues?.[0]?.[0];if(!K)return y;let $=bcs.bcs[_[E]];return y[E]=$.parse(new Uint8Array(K)),y},{}),z=this.formatResult(T,c),G=BigInt(T.interestRate??0),w=v[m];if(!w||w.error)throw new Error(`Failed to fetch interest config for ${c}`);let F=await this.#t(c,G,w);return {...z,...F}}))}};var cr="0x7f7351ef7e5089dfddf17f55abe028d719c45ca91d2c23e45a441ba65897f804",ur=async(s=new client.SuiClient({url:client.getFullnodeUrl("mainnet")}))=>{let r=[],e=[],t=null,o=true;for(;o;){let{data:n,nextCursor:a,hasNextPage:l}=await s.getDynamicFields({parentId:cr,cursor:t,limit:50});if(e.push(...n.map(p=>p.objectId)),n.length===0)break;t=a,o=l;}let i=await s.multiGetObjects({ids:e,options:{showContent:true}});for(let n of i){let a=n.data?.content;if(!a||a.dataType!=="moveObject")continue;let l=a.fields;r.push({address:l.value,type:`0x${l.name?.fields?.name}`});}return r.reduce((n,a)=>{let{name:l}=utils.parseStructTag(a.type);return n[l.replace(/_/g,"")]=a,n},{})};exports.DeepBookMarginPool=R;exports.DeepBookMarginToolkit=A;exports.getOnChainMarginPools=ur;
|
package/dist/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DeepBookConfig, MarginPoolContract, Coin } from '@mysten/deepbook-v3';
|
|
1
|
+
import { DeepBookConfig, MarginPoolContract, Coin, MarginPool } from '@mysten/deepbook-v3';
|
|
2
2
|
import { SuiClient } from '@mysten/sui/client';
|
|
3
3
|
import { Transaction } from '@mysten/sui/transactions';
|
|
4
4
|
|
|
@@ -84,6 +84,11 @@ declare class DeepBookMarginPool {
|
|
|
84
84
|
getPoolParameters(coinKey: string, supplierCapId?: string, tx?: Transaction): Promise<MarginPoolParams>;
|
|
85
85
|
getPoolParameters(coinKey: string, supplierCapId: string | undefined, tx: Transaction, inspect: true): Promise<MarginPoolParams>;
|
|
86
86
|
getPoolParameters(coinKey: string, supplierCapId: string | undefined, tx: Transaction, inspect: false): Promise<Transaction>;
|
|
87
|
+
getPoolsParameters(coinKeys: string[], supplierCapId?: string, tx?: Transaction): Promise<MarginPoolParams[]>;
|
|
88
|
+
getPoolsParameters(coinKeys: string[], supplierCapId: string | undefined, tx: Transaction, inspect: true): Promise<MarginPoolParams[]>;
|
|
89
|
+
getPoolsParameters(coinKeys: string[], supplierCapId: string | undefined, tx: Transaction, inspect: false): Promise<Transaction>;
|
|
87
90
|
}
|
|
88
91
|
|
|
89
|
-
|
|
92
|
+
declare const getOnChainMarginPools: (suiClient?: SuiClient) => Promise<Record<string, MarginPool>>;
|
|
93
|
+
|
|
94
|
+
export { DeepBookMarginPool, DeepBookMarginToolkit, type MarginBalance, type MarginCoinType, type MarginPoolParams, type NetworkType, type ReferralInfo, type ToolkitConfig, type TransactionResult, getOnChainMarginPools };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DeepBookConfig, MarginPoolContract, Coin } from '@mysten/deepbook-v3';
|
|
1
|
+
import { DeepBookConfig, MarginPoolContract, Coin, MarginPool } from '@mysten/deepbook-v3';
|
|
2
2
|
import { SuiClient } from '@mysten/sui/client';
|
|
3
3
|
import { Transaction } from '@mysten/sui/transactions';
|
|
4
4
|
|
|
@@ -84,6 +84,11 @@ declare class DeepBookMarginPool {
|
|
|
84
84
|
getPoolParameters(coinKey: string, supplierCapId?: string, tx?: Transaction): Promise<MarginPoolParams>;
|
|
85
85
|
getPoolParameters(coinKey: string, supplierCapId: string | undefined, tx: Transaction, inspect: true): Promise<MarginPoolParams>;
|
|
86
86
|
getPoolParameters(coinKey: string, supplierCapId: string | undefined, tx: Transaction, inspect: false): Promise<Transaction>;
|
|
87
|
+
getPoolsParameters(coinKeys: string[], supplierCapId?: string, tx?: Transaction): Promise<MarginPoolParams[]>;
|
|
88
|
+
getPoolsParameters(coinKeys: string[], supplierCapId: string | undefined, tx: Transaction, inspect: true): Promise<MarginPoolParams[]>;
|
|
89
|
+
getPoolsParameters(coinKeys: string[], supplierCapId: string | undefined, tx: Transaction, inspect: false): Promise<Transaction>;
|
|
87
90
|
}
|
|
88
91
|
|
|
89
|
-
|
|
92
|
+
declare const getOnChainMarginPools: (suiClient?: SuiClient) => Promise<Record<string, MarginPool>>;
|
|
93
|
+
|
|
94
|
+
export { DeepBookMarginPool, DeepBookMarginToolkit, type MarginBalance, type MarginCoinType, type MarginPoolParams, type NetworkType, type ReferralInfo, type ToolkitConfig, type TransactionResult, getOnChainMarginPools };
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import {getFullnodeUrl,SuiClient}from'@mysten/sui/client';import {Ed25519Keypair}from'@mysten/sui/keypairs/ed25519';import {Transaction}from'@mysten/sui/transactions';import {DeepBookConfig,MarginPoolContract,FLOAT_SCALAR}from'@mysten/deepbook-v3';import {SUI_PRIVATE_KEY_PREFIX,decodeSuiPrivateKey,LEGACY_PRIVATE_KEY_SIZE,PRIVATE_KEY_SIZE}from'@mysten/sui/cryptography';import {fromHex,fromBase64}from'@mysten/bcs';import {bcs}from'@mysten/sui/bcs';import {BigNumber}from'bignumber.js';var T=n=>/^0x[0-9a-fA-F]+$|^[0-9a-fA-F]+$/.test(n),B=n=>/^[a-zA-Z0-9+/]+={0,2}$/g.test(n),A=n=>{if(T(n))return fromHex(n);if(B(n))return fromBase64(n);throw new Error("The string is not a valid hex or base64 string.")},P=n=>{if(n.length===LEGACY_PRIVATE_KEY_SIZE)return n.slice(0,PRIVATE_KEY_SIZE);if(n.length===PRIVATE_KEY_SIZE+1&&n[0]===0)return n.slice(1);if(n.length===PRIVATE_KEY_SIZE)return n;throw new Error("invalid secret key")};var C=class{suiClient;keypair;address;marginPoolContract;supplierCapId;dbConfig;supplierCapPackageId;constructor({network:r,fullnodeUrl:i,supplierCapId:t,privateKey:e,supplierCapPackageId:o,dbConfig:a}){let s=i??getFullnodeUrl(r);this.suiClient=new SuiClient({url:s}),this.keypair=this.#r(e),this.address=this.keypair.getPublicKey().toSuiAddress(),this.supplierCapId=t,this.dbConfig=a??new DeepBookConfig({network:r,address:this.address}),this.marginPoolContract=new MarginPoolContract(this.dbConfig),this.supplierCapPackageId=o??this.dbConfig.MARGIN_PACKAGE_ID;}#r(r){if(r.startsWith(SUI_PRIVATE_KEY_PREFIX)){let{secretKey:i}=decodeSuiPrivateKey(r);return Ed25519Keypair.fromSecretKey(P(i))}return Ed25519Keypair.fromSecretKey(P(A(r)))}async#t(){let r=`${this.dbConfig.MARGIN_PACKAGE_ID}::margin_pool::SupplierCap`;return (await this.suiClient.getOwnedObjects({owner:this.address,filter:{StructType:r},options:{showType:true}})).data?.[0]?.data?.objectId}async initialize(){if(this.supplierCapId)return this.supplierCapId;let r=await this.#t();if(r)return this.supplierCapId=r,r;let i=await this.createSupplierCap();if(!i)throw new Error("Failed to create Supplier Cap");return this.supplierCapId=i,i}async createSupplierCap(){try{let r=new Transaction;r.setSender(this.address);let i=r.moveCall({target:`${this.supplierCapPackageId}::margin_pool::mint_supplier_cap`,arguments:[r.object(this.dbConfig.MARGIN_REGISTRY_ID),r.object.clock()]});r.transferObjects([i],r.pure.address(this.address));let t=await this.suiClient.signAndExecuteTransaction({signer:this.keypair,transaction:r,options:{showEffects:!0,showObjectChanges:!0}});if(t.errors&&t.errors.length>0)throw new Error(`Transaction failed with errors: ${t.errors.map(e=>e.toString()).join(", ")}`);if(t.objectChanges){for(let e of t.objectChanges)if(e.type==="created"&&e.objectType.includes("SupplierCap"))return e.objectId}return null}catch(r){throw new Error(`Failed to create Supplier Cap: ${r.message||r}`)}}async createSupplyReferral(r){try{let i=new Transaction;i.setSender(this.address);let t=this.dbConfig.getMarginPool(r);if(!t)throw new Error(`Margin pool configuration not found for coin: ${r}`);i.moveCall({target:`${this.dbConfig.MARGIN_PACKAGE_ID}::margin_pool::mint_supply_referral`,arguments:[i.object(t.address),i.object(this.dbConfig.MARGIN_REGISTRY_ID),i.object.clock()],typeArguments:[t.type]});let e=await this.suiClient.signAndExecuteTransaction({signer:this.keypair,transaction:i,options:{showEffects:!0,showObjectChanges:!0}});if(e.errors&&e.errors.length>0)throw new Error(`Transaction failed with errors: ${e.errors.map(o=>o.toString()).join(", ")}`);if(e.objectChanges){for(let o of e.objectChanges)if(o.type==="created"&&o.objectType.includes("SupplyReferral"))return o.objectId}return null}catch(i){throw new Error(`Failed to create Supply Referral: ${i.message||i}`)}}async supplyToMarginPool(r,i,t){try{if(!this.supplierCapId)throw new Error("Supplier Cap not initialized. Call initialize() first.");let e=new Transaction;e.setSender(this.address);let o=e.object(this.supplierCapId);e.add(this.marginPoolContract.supplyToMarginPool(r,o,i,t));let{errors:a}=await this.suiClient.signAndExecuteTransaction({signer:this.keypair,transaction:e,options:{showEffects:!0,showObjectChanges:!0}});if(a&&a.length>0)throw new Error(`Transaction failed with errors: ${a.map(s=>s.toString()).join(", ")}`);return !0}catch(e){throw new Error(`Failed to supply to margin pool: ${e.message||e}`)}}async withdrawFromMarginPool(r,i){try{if(!this.supplierCapId)throw new Error("Supplier Cap not initialized. Call initialize() first.");let t=new Transaction,e=t.object(this.supplierCapId),a=this.marginPoolContract.withdrawFromMarginPool(r,e,i)(t);t.transferObjects([a],this.address);let{errors:s}=await this.suiClient.signAndExecuteTransaction({signer:this.keypair,transaction:t,options:{showEffects:!0,showObjectChanges:!0}});if(s&&s.length>0)throw new Error(`Transaction failed with errors: ${s.map(p=>p.toString()).join(", ")}`);return !0}catch(t){throw new Error(`Failed to withdraw from margin pool: ${t.message||t}`)}}async withdrawReferralFees(r,i){try{let t=new Transaction;t.add(this.marginPoolContract.withdrawReferralFees(r,i));let{errors:e}=await this.suiClient.signAndExecuteTransaction({signer:this.keypair,transaction:t,options:{showEffects:!0,showObjectChanges:!0,showBalanceChanges:!0}});if(e&&e.length>0)throw new Error(`Transaction failed with errors: ${e.map(o=>o.toString()).join(", ")}`);return !0}catch(t){throw new Error(`Failed to withdraw referral fees: ${t.message||t}`)}}async getBalance(r){try{if(!this.supplierCapId)throw new Error("Supplier Cap not initialized. Call initialize() first.");let i=new Transaction;i.add(this.marginPoolContract.userSupplyAmount(r,this.supplierCapId));let t=await this.suiClient.devInspectTransactionBlock({sender:this.address,transactionBlock:i}),e=0;if(t&&t.results&&t.results[0]&&t.results[0].returnValues){let l=t.results[0].returnValues[0];if(l&&l[0]){let c=Buffer.from(l[0]).readBigUInt64LE(),m=this.dbConfig.getCoin(r).scalar;e=Number(c)/m;}}let o=this.dbConfig.getCoin(r).type,a=await this.suiClient.getBalance({owner:this.address,coinType:o}),s=this.dbConfig.getCoin(r).scalar,p=Number(a.totalBalance)/s;return {userSupplyAmount:e,walletBalance:p}}catch(i){throw new Error(`Failed to get balance: ${i.message||i}`)}}getSupplierCapId(){return this.supplierCapId}getAddress(){return this.address}};var w=["supplyCap","maxUtilizationRate","protocolSpread","minBorrow","interestRate","totalSupply","supplyShares","totalBorrow","borrowShares","lastUpdateTimestamp"],h=["userSupplyShares","userSupplyAmount"],_={supplyCap:"U64",maxUtilizationRate:"U64",protocolSpread:"U64",minBorrow:"U64",interestRate:"U64",totalSupply:"U64",supplyShares:"U64",totalBorrow:"U64",borrowShares:"U64",lastUpdateTimestamp:"U64",userSupplyShares:"U64",userSupplyAmount:"U64"};var d=(n,r)=>n*r/BigInt(FLOAT_SCALAR),u=n=>Number(n)/FLOAT_SCALAR;var W=new Set(h),D=n=>W.has(n),b=class{marginPoolContract;dbConfig;suiClient;constructor({network:r,address:i="",suiClient:t,dbConfig:e}={}){let o=r??e?.network??"mainnet";if(this.dbConfig=e??new DeepBookConfig({network:o,address:i}),this.suiClient=t??new SuiClient({url:getFullnodeUrl(o)}),this.marginPoolContract=new MarginPoolContract(this.dbConfig),r!==void 0&&e!==void 0&&r!==e.network)throw new Error(`Mismatch between provided network (${r}) and dbConfig network (${e.network}).`)}get network(){return this.dbConfig.network}#r(r,i,t,e){if(D(i)){let o=this.marginPoolContract[i];if(e==null)throw new Error(`supplierCap is required for '${i}'.`);r.add(o(t,e));}else {let o=this.marginPoolContract[i];r.add(o(t));}}parseInspectResultToBcsStructs(r,i){let t=r.results;if(!t)throw new Error("No results found in DevInspect output.");return i.reduce((e,o,a)=>{let s=t[a]?.returnValues?.[0]?.[0];if(!s)return e;let p=bcs[_[o]];return e[o]=p.parse(new Uint8Array(s)),e},{})}formatResult(r,i){let t=this.dbConfig.getCoin(i),e={supplyCap:0,maxUtilizationRate:0,protocolSpread:0,minBorrow:0,interestRate:0,totalSupply:0,supplyShares:0,totalBorrow:0,borrowShares:0,lastUpdateTimestamp:0,userSupplyShares:0,userSupplyAmount:0,decimals:t.scalar.toString().length-1,highKink:0,baseBorrowApr:0,borrowAprOnHighKink:0,maxBorrowApr:0,supplyApr:0,utilizationRate:0,...t};if(!t)return e;let o=new Set(["interestRate","maxUtilizationRate","protocolSpread"]);for(let[a,s]of Object.entries(r))a==="lastUpdateTimestamp"?e[a]=Number(s):o.has(a)?e[a]=new BigNumber(s).dividedBy(FLOAT_SCALAR).toNumber():e[a]=new BigNumber(s).dividedBy(t.scalar).toNumber();return e}computeBorrowAprAtUtil(r,i){let t=BigInt(i.base_rate),e=BigInt(i.base_slope),o=BigInt(i.excess_slope),a=BigInt(i.optimal_utilization);return r<a?t+d(r,e):t+d(a,e)+d(r-a,o)}calculateKinksAndRate(r,i,t,e){let o=BigInt(r.optimal_utilization),a=BigInt(i.max_utilization_rate),s=this.computeBorrowAprAtUtil(o,r),p=this.computeBorrowAprAtUtil(a,r),l=BigInt(BigNumber(t.total_borrow).dividedBy(t.total_supply).shiftedBy(9).decimalPlaces(0).toString()),c=d(d(e,l),BigInt(FLOAT_SCALAR)-BigInt(i.protocol_spread));return {raw:{baseBorrowApr:r.base_rate,highKink:o,borrowAprOnHighKink:s,maxBorrowApr:p,supplyApr:c,utilizationRate:l},normalized:{baseBorrowApr:u(BigInt(r.base_rate)),highKink:u(o),borrowAprOnHighKink:u(s),maxBorrowApr:u(p),supplyApr:u(c),utilizationRate:u(l)}}}async#t(r,i){let{address:t}=this.dbConfig.getMarginPool(r),o=((await this.suiClient.getObject({id:t,options:{showContent:true}})).data?.content).fields,a=o.config.fields,s=a.interest_config.fields,p=a.margin_pool_config.fields,l=o.state.fields,{normalized:c}=this.calculateKinksAndRate(s,p,l,i);return c}async getPoolParameters(r,i,t=new Transaction,e=true){if(w.forEach(m=>this.#r(t,m,r)),i&&h.forEach(m=>this.#r(t,m,r,i)),!e)return t;let o=[...w,...h],a=await this.suiClient.devInspectTransactionBlock({transactionBlock:t,sender:this.dbConfig.address}),s=this.parseInspectResultToBcsStructs(a,o),p=this.formatResult(s,r),l=BigInt(s.interestRate??0),c=await this.#t(r,l);return {...p,...c}}};export{b as DeepBookMarginPool,C as DeepBookMarginToolkit};
|
|
1
|
+
import {SuiClient,getFullnodeUrl}from'@mysten/sui/client';import {Ed25519Keypair}from'@mysten/sui/keypairs/ed25519';import {Transaction}from'@mysten/sui/transactions';import {DeepBookConfig,MarginPoolContract,FLOAT_SCALAR}from'@mysten/deepbook-v3';import {SUI_PRIVATE_KEY_PREFIX,decodeSuiPrivateKey,LEGACY_PRIVATE_KEY_SIZE,PRIVATE_KEY_SIZE}from'@mysten/sui/cryptography';import {fromHex,fromBase64}from'@mysten/bcs';import {bcs}from'@mysten/sui/bcs';import {BigNumber}from'bignumber.js';import {parseStructTag}from'@mysten/sui/utils';var H=s=>/^0x[0-9a-fA-F]+$|^[0-9a-fA-F]+$/.test(s),V=s=>/^[a-zA-Z0-9+/]+={0,2}$/g.test(s),B=s=>{if(H(s))return fromHex(s);if(V(s))return fromBase64(s);throw new Error("The string is not a valid hex or base64 string.")},S=s=>{if(s.length===LEGACY_PRIVATE_KEY_SIZE)return s.slice(0,PRIVATE_KEY_SIZE);if(s.length===PRIVATE_KEY_SIZE+1&&s[0]===0)return s.slice(1);if(s.length===PRIVATE_KEY_SIZE)return s;throw new Error("invalid secret key")};var A=class{suiClient;keypair;address;marginPoolContract;supplierCapId;dbConfig;supplierCapPackageId;constructor({network:r,fullnodeUrl:e,supplierCapId:t,privateKey:o,supplierCapPackageId:i,dbConfig:n}){let a=e??getFullnodeUrl(r);this.suiClient=new SuiClient({url:a}),this.keypair=this.#r(o),this.address=this.keypair.getPublicKey().toSuiAddress(),this.supplierCapId=t,this.dbConfig=n??new DeepBookConfig({network:r,address:this.address}),this.marginPoolContract=new MarginPoolContract(this.dbConfig),this.supplierCapPackageId=i??this.dbConfig.MARGIN_PACKAGE_ID;}#r(r){if(r.startsWith(SUI_PRIVATE_KEY_PREFIX)){let{secretKey:e}=decodeSuiPrivateKey(r);return Ed25519Keypair.fromSecretKey(S(e))}return Ed25519Keypair.fromSecretKey(S(B(r)))}async#t(){let r=`${this.dbConfig.MARGIN_PACKAGE_ID}::margin_pool::SupplierCap`;return (await this.suiClient.getOwnedObjects({owner:this.address,filter:{StructType:r},options:{showType:true}})).data?.[0]?.data?.objectId}async initialize(){if(this.supplierCapId)return this.supplierCapId;let r=await this.#t();if(r)return this.supplierCapId=r,r;let e=await this.createSupplierCap();if(!e)throw new Error("Failed to create Supplier Cap");return this.supplierCapId=e,e}async createSupplierCap(){try{let r=new Transaction;r.setSender(this.address);let e=r.moveCall({target:`${this.supplierCapPackageId}::margin_pool::mint_supplier_cap`,arguments:[r.object(this.dbConfig.MARGIN_REGISTRY_ID),r.object.clock()]});r.transferObjects([e],r.pure.address(this.address));let t=await this.suiClient.signAndExecuteTransaction({signer:this.keypair,transaction:r,options:{showEffects:!0,showObjectChanges:!0}});if(t.errors&&t.errors.length>0)throw new Error(`Transaction failed with errors: ${t.errors.map(o=>o.toString()).join(", ")}`);if(t.objectChanges){for(let o of t.objectChanges)if(o.type==="created"&&o.objectType.includes("SupplierCap"))return o.objectId}return null}catch(r){throw new Error(`Failed to create Supplier Cap: ${r.message||r}`)}}async createSupplyReferral(r){try{let e=new Transaction;e.setSender(this.address);let t=this.dbConfig.getMarginPool(r);if(!t)throw new Error(`Margin pool configuration not found for coin: ${r}`);e.moveCall({target:`${this.dbConfig.MARGIN_PACKAGE_ID}::margin_pool::mint_supply_referral`,arguments:[e.object(t.address),e.object(this.dbConfig.MARGIN_REGISTRY_ID),e.object.clock()],typeArguments:[t.type]});let o=await this.suiClient.signAndExecuteTransaction({signer:this.keypair,transaction:e,options:{showEffects:!0,showObjectChanges:!0}});if(o.errors&&o.errors.length>0)throw new Error(`Transaction failed with errors: ${o.errors.map(i=>i.toString()).join(", ")}`);if(o.objectChanges){for(let i of o.objectChanges)if(i.type==="created"&&i.objectType.includes("SupplyReferral"))return i.objectId}return null}catch(e){throw new Error(`Failed to create Supply Referral: ${e.message||e}`)}}async supplyToMarginPool(r,e,t){try{if(!this.supplierCapId)throw new Error("Supplier Cap not initialized. Call initialize() first.");let o=new Transaction;o.setSender(this.address);let i=o.object(this.supplierCapId);o.add(this.marginPoolContract.supplyToMarginPool(r,i,e,t));let{errors:n}=await this.suiClient.signAndExecuteTransaction({signer:this.keypair,transaction:o,options:{showEffects:!0,showObjectChanges:!0}});if(n&&n.length>0)throw new Error(`Transaction failed with errors: ${n.map(a=>a.toString()).join(", ")}`);return !0}catch(o){throw new Error(`Failed to supply to margin pool: ${o.message||o}`)}}async withdrawFromMarginPool(r,e){try{if(!this.supplierCapId)throw new Error("Supplier Cap not initialized. Call initialize() first.");let t=new Transaction,o=t.object(this.supplierCapId),n=this.marginPoolContract.withdrawFromMarginPool(r,o,e)(t);t.transferObjects([n],this.address);let{errors:a}=await this.suiClient.signAndExecuteTransaction({signer:this.keypair,transaction:t,options:{showEffects:!0,showObjectChanges:!0}});if(a&&a.length>0)throw new Error(`Transaction failed with errors: ${a.map(l=>l.toString()).join(", ")}`);return !0}catch(t){throw new Error(`Failed to withdraw from margin pool: ${t.message||t}`)}}async withdrawReferralFees(r,e){try{let t=new Transaction;t.add(this.marginPoolContract.withdrawReferralFees(r,e));let{errors:o}=await this.suiClient.signAndExecuteTransaction({signer:this.keypair,transaction:t,options:{showEffects:!0,showObjectChanges:!0,showBalanceChanges:!0}});if(o&&o.length>0)throw new Error(`Transaction failed with errors: ${o.map(i=>i.toString()).join(", ")}`);return !0}catch(t){throw new Error(`Failed to withdraw referral fees: ${t.message||t}`)}}async getBalance(r){try{if(!this.supplierCapId)throw new Error("Supplier Cap not initialized. Call initialize() first.");let e=new Transaction;e.add(this.marginPoolContract.userSupplyAmount(r,this.supplierCapId));let t=await this.suiClient.devInspectTransactionBlock({sender:this.address,transactionBlock:e}),o=0;if(t&&t.results&&t.results[0]&&t.results[0].returnValues){let p=t.results[0].returnValues[0];if(p&&p[0]){let u=Buffer.from(p[0]).readBigUInt64LE(),g=this.dbConfig.getCoin(r).scalar;o=Number(u)/g;}}let i=this.dbConfig.getCoin(r).type,n=await this.suiClient.getBalance({owner:this.address,coinType:i}),a=this.dbConfig.getCoin(r).scalar,l=Number(n.totalBalance)/a;return {userSupplyAmount:o,walletBalance:l}}catch(e){throw new Error(`Failed to get balance: ${e.message||e}`)}}getSupplierCapId(){return this.supplierCapId}getAddress(){return this.address}};var C=["supplyCap","maxUtilizationRate","protocolSpread","minBorrow","interestRate","totalSupply","supplyShares","totalBorrow","borrowShares","lastUpdateTimestamp"],f=["userSupplyShares","userSupplyAmount"],_={supplyCap:"U64",maxUtilizationRate:"U64",protocolSpread:"U64",minBorrow:"U64",interestRate:"U64",totalSupply:"U64",supplyShares:"U64",totalBorrow:"U64",borrowShares:"U64",lastUpdateTimestamp:"U64",userSupplyShares:"U64",userSupplyAmount:"U64"};var P=(s,r)=>s*r/BigInt(FLOAT_SCALAR),d=s=>Number(s)/FLOAT_SCALAR;var nr=new Set(f),ar=s=>nr.has(s),R=class{marginPoolContract;dbConfig;suiClient;constructor({network:r,address:e="",suiClient:t,dbConfig:o}={}){let i=r??o?.network??"mainnet";if(this.dbConfig=o??new DeepBookConfig({network:i,address:e}),this.suiClient=t??new SuiClient({url:getFullnodeUrl(i)}),this.marginPoolContract=new MarginPoolContract(this.dbConfig),r!==void 0&&o!==void 0&&r!==o.network)throw new Error(`Mismatch between provided network (${r}) and dbConfig network (${o.network}).`)}get network(){return this.dbConfig.network}#r(r,e,t,o){if(ar(e)){let i=this.marginPoolContract[e];if(o==null)throw new Error(`supplierCap is required for '${e}'.`);r.add(i(t,o));}else {let i=this.marginPoolContract[e];r.add(i(t));}}parseInspectResultToBcsStructs(r,e){let t=r.results;if(!t)throw new Error("No results found in DevInspect output.");return e.reduce((o,i,n)=>{let a=t[n]?.returnValues?.[0]?.[0];if(!a)return o;let l=bcs[_[i]];return o[i]=l.parse(new Uint8Array(a)),o},{})}formatResult(r,e){let t=this.dbConfig.getCoin(e),o={supplyCap:0,maxUtilizationRate:0,protocolSpread:0,minBorrow:0,interestRate:0,totalSupply:0,supplyShares:0,totalBorrow:0,borrowShares:0,lastUpdateTimestamp:0,userSupplyShares:0,userSupplyAmount:0,decimals:t.scalar.toString().length-1,highKink:0,baseBorrowApr:0,borrowAprOnHighKink:0,maxBorrowApr:0,supplyApr:0,utilizationRate:0,...t};if(!t)return o;let i=new Set(["interestRate","maxUtilizationRate","protocolSpread"]);for(let[n,a]of Object.entries(r))n==="lastUpdateTimestamp"?o[n]=Number(a):i.has(n)?o[n]=new BigNumber(a).dividedBy(FLOAT_SCALAR).toNumber():o[n]=new BigNumber(a).dividedBy(t.scalar).toNumber();return o}computeBorrowAprAtUtil(r,e){let t=BigInt(e.base_rate),o=BigInt(e.base_slope),i=BigInt(e.excess_slope),n=BigInt(e.optimal_utilization);return r<n?t+P(r,o):t+P(n,o)+P(r-n,i)}calculateKinksAndRate(r,e,t,o){let i=BigInt(r.optimal_utilization),n=BigInt(e.max_utilization_rate),a=this.computeBorrowAprAtUtil(i,r),l=this.computeBorrowAprAtUtil(n,r),p=BigInt(BigNumber(t.total_borrow).dividedBy(t.total_supply).shiftedBy(9).decimalPlaces(0).toString()),u=P(P(o,p),BigInt(FLOAT_SCALAR)-BigInt(e.protocol_spread));return {raw:{baseBorrowApr:r.base_rate,highKink:i,borrowAprOnHighKink:a,maxBorrowApr:l,supplyApr:u,utilizationRate:p},normalized:{baseBorrowApr:d(BigInt(r.base_rate)),highKink:d(i),borrowAprOnHighKink:d(a),maxBorrowApr:d(l),supplyApr:d(u),utilizationRate:d(p)}}}async#t(r,e,t){let{address:o}=this.dbConfig.getMarginPool(r);t??=await this.suiClient.getObject({id:o,options:{showContent:true}});let i=(t.data?.content).fields,n=i.config.fields,a=n.interest_config.fields,l=n.margin_pool_config.fields,p=i.state.fields,{normalized:u}=this.calculateKinksAndRate(a,l,p,e);return u}async getPoolParameters(r,e,t=new Transaction,o=true){if(C.forEach(g=>this.#r(t,g,r)),e&&f.forEach(g=>this.#r(t,g,r,e)),!o)return t;let i=[...C,...f],n=await this.suiClient.devInspectTransactionBlock({transactionBlock:t,sender:this.dbConfig.address}),a=this.parseInspectResultToBcsStructs(n,i),l=this.formatResult(a,r),p=BigInt(a.interestRate??0),u=await this.#t(r,p);return {...l,...u}}async getPoolsParameters(r,e,t=new Transaction,o=true){for(let c of r)C.forEach(m=>this.#r(t,m,c)),e&&f.forEach(m=>this.#r(t,m,c,e));if(!o)return t;let i=[...C,...e?f:[]],n=i.length,a=r.map(c=>this.dbConfig.getMarginPool(c).address),l=50,p=[];for(let c=0;c<a.length;c+=l)p.push(a.slice(c,c+l));let[u,...g]=await Promise.all([this.suiClient.devInspectTransactionBlock({transactionBlock:t,sender:this.dbConfig.address}),...p.map(c=>this.suiClient.multiGetObjects({ids:c,options:{showContent:true}}))]),v=g.flat(),I=u.results;if(!I)throw new Error("No results found in DevInspect output.");return Promise.all(r.map(async(c,m)=>{let N=m*n,T=i.reduce((y,E,L)=>{let K=I[N+L]?.returnValues?.[0]?.[0];if(!K)return y;let $=bcs[_[E]];return y[E]=$.parse(new Uint8Array(K)),y},{}),z=this.formatResult(T,c),G=BigInt(T.interestRate??0),w=v[m];if(!w||w.error)throw new Error(`Failed to fetch interest config for ${c}`);let F=await this.#t(c,G,w);return {...z,...F}}))}};var cr="0x7f7351ef7e5089dfddf17f55abe028d719c45ca91d2c23e45a441ba65897f804",ur=async(s=new SuiClient({url:getFullnodeUrl("mainnet")}))=>{let r=[],e=[],t=null,o=true;for(;o;){let{data:n,nextCursor:a,hasNextPage:l}=await s.getDynamicFields({parentId:cr,cursor:t,limit:50});if(e.push(...n.map(p=>p.objectId)),n.length===0)break;t=a,o=l;}let i=await s.multiGetObjects({ids:e,options:{showContent:true}});for(let n of i){let a=n.data?.content;if(!a||a.dataType!=="moveObject")continue;let l=a.fields;r.push({address:l.value,type:`0x${l.name?.fields?.name}`});}return r.reduce((n,a)=>{let{name:l}=parseStructTag(a.type);return n[l.replace(/_/g,"")]=a,n},{})};export{R as DeepBookMarginPool,A as DeepBookMarginToolkit,ur as getOnChainMarginPools};
|
package/package.json
CHANGED
|
@@ -18,22 +18,31 @@ const MARGIN_POOLS = {
|
|
|
18
18
|
address: '0x38decd3dbb62bd4723144349bf57bc403b393aee86a51596846a824a1e0c2c01',
|
|
19
19
|
type: '0x356a26eb9e012a68958082340d4c4116e7f55615cf27affcff209cf0ae544f59::wal::WAL',
|
|
20
20
|
},
|
|
21
|
+
XBTC: {
|
|
22
|
+
address: '0x14dfbf54400e0b97e892349310d392bef6d187c2b6709d9b246b8f41c9a13de4',
|
|
23
|
+
type: '0x876a4b7bce8aeaef60464c11f4026903e9afacab79b9b142686158aa86560b50::xbtc::XBTC',
|
|
24
|
+
},
|
|
25
|
+
SUIUSDE: {
|
|
26
|
+
address: '0xbb990ca04a7743e6c0a25a7fb16f60fc6f6d8bf213624ff03a63f1bb04c3a12f',
|
|
27
|
+
type: '0x41d587e5336f1c86cad50d38a7136db99333bb9bda91cea4ba69115defeb1402::sui_usde::SUI_USDE',
|
|
28
|
+
},
|
|
21
29
|
};
|
|
22
30
|
|
|
23
31
|
const main = async () => {
|
|
24
32
|
try {
|
|
25
|
-
const
|
|
33
|
+
const network = 'mainnet';
|
|
26
34
|
const dbMarginPool = new DeepBookMarginPool({
|
|
27
|
-
|
|
35
|
+
network,
|
|
28
36
|
dbConfig: new DeepBookConfig({
|
|
29
|
-
|
|
37
|
+
network,
|
|
30
38
|
address: '',
|
|
31
39
|
marginPools: MARGIN_POOLS,
|
|
32
40
|
}),
|
|
33
41
|
});
|
|
34
|
-
const
|
|
35
|
-
const
|
|
36
|
-
console.log(
|
|
42
|
+
const coinKeys = ['USDC', 'XBTC'];
|
|
43
|
+
const suiMarginPoolsParams = await dbMarginPool.getPoolsParameters(coinKeys);
|
|
44
|
+
console.log('Margin Pools Parameters:');
|
|
45
|
+
console.log(JSON.stringify(suiMarginPoolsParams, null, 2));
|
|
37
46
|
} catch (error) {
|
|
38
47
|
console.error('An error occurred:', error);
|
|
39
48
|
} finally {
|
package/src/index.ts
CHANGED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { MarginPool } from '@mysten/deepbook-v3';
|
|
2
|
+
import { getFullnodeUrl, SuiClient } from '@mysten/sui/client';
|
|
3
|
+
import { parseStructTag } from '@mysten/sui/utils';
|
|
4
|
+
|
|
5
|
+
const MARGIN_POOLS_TABLE_ID = '0x7f7351ef7e5089dfddf17f55abe028d719c45ca91d2c23e45a441ba65897f804';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Fetch all margin pool addresses and their types from the on-chain dynamic fields table.
|
|
9
|
+
* @returns Record<coinKey, { address: string; type: string }>
|
|
10
|
+
*/
|
|
11
|
+
export const getOnChainMarginPools = async (
|
|
12
|
+
suiClient: SuiClient = new SuiClient({
|
|
13
|
+
url: getFullnodeUrl('mainnet'),
|
|
14
|
+
})
|
|
15
|
+
) => {
|
|
16
|
+
const marginPools: Array<{ address: string; type: string }> = [];
|
|
17
|
+
const ids: string[] = [];
|
|
18
|
+
|
|
19
|
+
let cursor: string | null = null;
|
|
20
|
+
let nextPage = true;
|
|
21
|
+
|
|
22
|
+
while (nextPage) {
|
|
23
|
+
const { data, nextCursor, hasNextPage } = await suiClient.getDynamicFields({
|
|
24
|
+
parentId: MARGIN_POOLS_TABLE_ID,
|
|
25
|
+
cursor,
|
|
26
|
+
limit: 50,
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
ids.push(...data.map((item) => item.objectId));
|
|
30
|
+
|
|
31
|
+
if (data.length === 0) {
|
|
32
|
+
break;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
cursor = nextCursor;
|
|
36
|
+
nextPage = hasNextPage;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Fetch all the object ids
|
|
40
|
+
const objects = await suiClient.multiGetObjects({ ids, options: { showContent: true } });
|
|
41
|
+
|
|
42
|
+
for (const obj of objects) {
|
|
43
|
+
const content = obj.data?.content;
|
|
44
|
+
if (!content || content.dataType !== 'moveObject') continue;
|
|
45
|
+
const fields = content.fields as Record<string, any>;
|
|
46
|
+
marginPools.push({
|
|
47
|
+
address: fields.value,
|
|
48
|
+
type: `0x${fields.name?.fields?.name}`,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return marginPools.reduce(
|
|
53
|
+
(acc, pool) => {
|
|
54
|
+
// Get symbol from type
|
|
55
|
+
const { name } = parseStructTag(pool.type);
|
|
56
|
+
acc[name.replace(/_/g, '')] = pool;
|
|
57
|
+
return acc;
|
|
58
|
+
},
|
|
59
|
+
{} as Record<string, MarginPool>
|
|
60
|
+
);
|
|
61
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { getOnChainMarginPools } from './getOnChainMarginPools';
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { Coin, DeepBookConfig, FLOAT_SCALAR, MarginPoolContract } from '@mysten/deepbook-v3';
|
|
2
2
|
import { bcs } from '@mysten/sui/bcs';
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
DevInspectResults,
|
|
5
|
+
getFullnodeUrl,
|
|
6
|
+
SuiClient,
|
|
7
|
+
SuiObjectResponse,
|
|
8
|
+
} from '@mysten/sui/client';
|
|
4
9
|
import { Transaction } from '@mysten/sui/transactions';
|
|
5
10
|
import { BigNumber } from 'bignumber.js';
|
|
6
11
|
import {
|
|
@@ -87,7 +92,12 @@ export class DeepBookMarginPool {
|
|
|
87
92
|
// If dbConfig is provided and network is not, derive network from dbConfig
|
|
88
93
|
const resolvedNetwork = network ?? dbConfig?.network ?? 'mainnet';
|
|
89
94
|
|
|
90
|
-
this.dbConfig =
|
|
95
|
+
this.dbConfig =
|
|
96
|
+
dbConfig ??
|
|
97
|
+
new DeepBookConfig({
|
|
98
|
+
network: resolvedNetwork,
|
|
99
|
+
address,
|
|
100
|
+
});
|
|
91
101
|
this.suiClient = suiClient ?? new SuiClient({ url: getFullnodeUrl(resolvedNetwork) });
|
|
92
102
|
|
|
93
103
|
// Initialize smart contract wrapper
|
|
@@ -309,9 +319,9 @@ export class DeepBookMarginPool {
|
|
|
309
319
|
* @param coinKey - Asset key.
|
|
310
320
|
* @param borrowAprScaled - interestRate in FLOAT_SCALAR scale (bigint).
|
|
311
321
|
*/
|
|
312
|
-
async #getInterestConfig(coinKey: string, borrowAprScaled: bigint) {
|
|
322
|
+
async #getInterestConfig(coinKey: string, borrowAprScaled: bigint, response?: SuiObjectResponse) {
|
|
313
323
|
const { address } = this.dbConfig.getMarginPool(coinKey);
|
|
314
|
-
|
|
324
|
+
response ??= await this.suiClient.getObject({
|
|
315
325
|
id: address,
|
|
316
326
|
options: {
|
|
317
327
|
showContent: true,
|
|
@@ -368,7 +378,6 @@ export class DeepBookMarginPool {
|
|
|
368
378
|
inspect: false
|
|
369
379
|
): Promise<Transaction>;
|
|
370
380
|
|
|
371
|
-
// 👇 implementation signature (must be last)
|
|
372
381
|
async getPoolParameters(
|
|
373
382
|
coinKey: string,
|
|
374
383
|
supplierCapId?: string,
|
|
@@ -409,4 +418,125 @@ export class DeepBookMarginPool {
|
|
|
409
418
|
...interestData,
|
|
410
419
|
};
|
|
411
420
|
}
|
|
421
|
+
|
|
422
|
+
/**
|
|
423
|
+
* Batch version of getPoolParameters for reduced RPC calls.
|
|
424
|
+
* Adds all param calls to a single transaction and performs one devInspect.
|
|
425
|
+
*
|
|
426
|
+
* @param coinKeys - Asset keys.
|
|
427
|
+
* @param supplierCapId - Supplier cap object ID.
|
|
428
|
+
* @param tx - Optional transaction to append to.
|
|
429
|
+
* @param inspect - Whether to perform devInspect and return decoded results.
|
|
430
|
+
*
|
|
431
|
+
* @returns Parsed parameters or transaction object ready for execution.
|
|
432
|
+
*/
|
|
433
|
+
async getPoolsParameters(
|
|
434
|
+
coinKeys: string[],
|
|
435
|
+
supplierCapId?: string,
|
|
436
|
+
tx?: Transaction
|
|
437
|
+
): Promise<MarginPoolParams[]>;
|
|
438
|
+
|
|
439
|
+
async getPoolsParameters(
|
|
440
|
+
coinKeys: string[],
|
|
441
|
+
supplierCapId: string | undefined,
|
|
442
|
+
tx: Transaction,
|
|
443
|
+
inspect: true
|
|
444
|
+
): Promise<MarginPoolParams[]>;
|
|
445
|
+
|
|
446
|
+
async getPoolsParameters(
|
|
447
|
+
coinKeys: string[],
|
|
448
|
+
supplierCapId: string | undefined,
|
|
449
|
+
tx: Transaction,
|
|
450
|
+
inspect: false
|
|
451
|
+
): Promise<Transaction>;
|
|
452
|
+
|
|
453
|
+
async getPoolsParameters(
|
|
454
|
+
coinKeys: string[],
|
|
455
|
+
supplierCapId?: string,
|
|
456
|
+
tx: Transaction = new Transaction(),
|
|
457
|
+
inspect: boolean = true
|
|
458
|
+
): Promise<MarginPoolParams[] | Transaction> {
|
|
459
|
+
// Add all param calls for every coin into a single transaction
|
|
460
|
+
for (const coinKey of coinKeys) {
|
|
461
|
+
MARGIN_POOL_PARAM_KEYS.forEach((paramKey) => this.#addParamCall(tx, paramKey, coinKey));
|
|
462
|
+
|
|
463
|
+
if (supplierCapId) {
|
|
464
|
+
MARGIN_POOL_W_SUPPLIER_CAP_PARAM_KEYS.forEach((paramKey) =>
|
|
465
|
+
this.#addParamCall(tx, paramKey, coinKey, supplierCapId)
|
|
466
|
+
);
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
if (!inspect) return tx;
|
|
471
|
+
|
|
472
|
+
// Determine how many result slots each coin occupies
|
|
473
|
+
const keysPerCoin: (MarginPoolParamKey | MarginPoolWithSupplierCapParamKey)[] = [
|
|
474
|
+
...MARGIN_POOL_PARAM_KEYS,
|
|
475
|
+
...(supplierCapId ? MARGIN_POOL_W_SUPPLIER_CAP_PARAM_KEYS : []),
|
|
476
|
+
];
|
|
477
|
+
const slotCount = keysPerCoin.length;
|
|
478
|
+
|
|
479
|
+
// Single devInspect + batched multiGetObjects (max 50 per call)
|
|
480
|
+
const objectIds = coinKeys.map((coinKey) => this.dbConfig.getMarginPool(coinKey).address);
|
|
481
|
+
const MULTI_GET_BATCH_SIZE = 50;
|
|
482
|
+
const batches: string[][] = [];
|
|
483
|
+
for (let i = 0; i < objectIds.length; i += MULTI_GET_BATCH_SIZE) {
|
|
484
|
+
batches.push(objectIds.slice(i, i + MULTI_GET_BATCH_SIZE));
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
const [inspectResult, ...objectBatches] = await Promise.all([
|
|
488
|
+
this.suiClient.devInspectTransactionBlock({
|
|
489
|
+
transactionBlock: tx,
|
|
490
|
+
sender: this.dbConfig.address,
|
|
491
|
+
}),
|
|
492
|
+
...batches.map((ids) =>
|
|
493
|
+
this.suiClient.multiGetObjects({
|
|
494
|
+
ids,
|
|
495
|
+
options: { showContent: true },
|
|
496
|
+
})
|
|
497
|
+
),
|
|
498
|
+
]);
|
|
499
|
+
const interestConfigs = objectBatches.flat();
|
|
500
|
+
|
|
501
|
+
const allResults = inspectResult.results;
|
|
502
|
+
if (!allResults) throw new Error('No results found in DevInspect output.');
|
|
503
|
+
|
|
504
|
+
// Split results per coin and format
|
|
505
|
+
return Promise.all(
|
|
506
|
+
coinKeys.map(async (coinKey, coinIdx) => {
|
|
507
|
+
const offset = coinIdx * slotCount;
|
|
508
|
+
|
|
509
|
+
// Parse the slice of results belonging to this coin
|
|
510
|
+
const parsed = keysPerCoin.reduce(
|
|
511
|
+
(acc, key, keyIdx) => {
|
|
512
|
+
const bytes = allResults[offset + keyIdx]?.returnValues?.[0]?.[0];
|
|
513
|
+
if (!bytes) return acc;
|
|
514
|
+
const bcsType = bcs[MARGIN_POOL_PARAM_KEY_STRUCT_MAP[key]];
|
|
515
|
+
acc[key] = bcsType.parse(new Uint8Array(bytes));
|
|
516
|
+
return acc;
|
|
517
|
+
},
|
|
518
|
+
{} as Record<MarginPoolParamKey | MarginPoolWithSupplierCapParamKey, string>
|
|
519
|
+
);
|
|
520
|
+
|
|
521
|
+
const formattedResult = this.formatResult(parsed, coinKey);
|
|
522
|
+
const borrowAprScaled = BigInt(parsed.interestRate ?? 0);
|
|
523
|
+
|
|
524
|
+
const interestConfig = interestConfigs[coinIdx];
|
|
525
|
+
if (!interestConfig || interestConfig.error) {
|
|
526
|
+
throw new Error(`Failed to fetch interest config for ${coinKey}`);
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
const interestData = await this.#getInterestConfig(
|
|
530
|
+
coinKey,
|
|
531
|
+
borrowAprScaled,
|
|
532
|
+
interestConfig
|
|
533
|
+
);
|
|
534
|
+
|
|
535
|
+
return {
|
|
536
|
+
...formattedResult,
|
|
537
|
+
...interestData,
|
|
538
|
+
};
|
|
539
|
+
})
|
|
540
|
+
);
|
|
541
|
+
}
|
|
412
542
|
}
|