@evaafi/sdk 0.2.0 → 0.3.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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # EVAA SDK
2
2
 
3
- The EVAA SDK is designed to easily integrate with EVAA lending protocol.
3
+ The EVAA SDK is designed to easily integrate with the EVAA lending protocol on TON blockchain.
4
4
 
5
5
  ## Documentation
6
6
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@evaafi/sdk",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "SDK for EVAA contracts",
5
5
  "main": "dist/index.js",
6
6
  "files": [
@@ -18,21 +18,17 @@
18
18
  "license": "MIT",
19
19
  "homepage": "https://github.com/evaafi/sdk#readme",
20
20
  "devDependencies": {
21
- "@types/node": "^20.10.4",
22
- "prettier": "^3.2.4",
23
- "ts-node": "^10.9.1",
24
- "typescript": "^5.3.3",
25
21
  "@ton/core": "0.56.0",
26
22
  "@tonconnect/sdk": "^3.0.0",
23
+ "@types/node": "^20.10.4",
27
24
  "crypto-js": "^4.2.0",
28
- "ethereumjs-util": "7.0.10",
29
- "ethers": "5.6.9"
25
+ "prettier": "^3.2.4",
26
+ "ts-node": "^10.9.1",
27
+ "typescript": "^5.3.3"
30
28
  },
31
29
  "peerDependencies": {
32
30
  "@ton/core": ">=0.56.0",
33
31
  "@tonconnect/sdk": ">=3.0.0",
34
- "crypto-js": ">=4.2.0",
35
- "ethereumjs-util": "7.0.10",
36
- "ethers": "5.6.9"
32
+ "crypto-js": ">=4.2.0"
37
33
  }
38
34
  }
package/src/api/parser.ts CHANGED
@@ -57,16 +57,17 @@ export function createAssetConfig(): DictionaryValue<AssetConfig> {
57
57
  const oracle = src.loadUintBig(256);
58
58
  const decimals = BigInt(src.loadUint(8));
59
59
  const ref = src.loadRef().beginParse();
60
- const collateralFactor = BigInt(ref.loadUint(16));
61
- const liquidationThreshold = BigInt(ref.loadUint(16));
62
- const liquidationBonus = BigInt(ref.loadUint(16));
63
- const baseBorrowRate = BigInt(ref.loadUint(64));
64
- const borrowRateSlopeLow = BigInt(ref.loadUint(64));
65
- const borrowRateSlopeHigh = BigInt(ref.loadUint(64));
66
- const supplyRateSlopeLow = BigInt(ref.loadUint(64));
67
- const supplyRateSlopeHigh = BigInt(ref.loadUint(64));
68
- const targetUtilization = BigInt(ref.loadUint(64));
69
- const originationFee = BigInt(ref.loadUint(64));
60
+ const collateralFactor = ref.loadUintBig(16);
61
+ const liquidationThreshold = ref.loadUintBig(16);
62
+ const liquidationBonus = ref.loadUintBig(16);
63
+ const baseBorrowRate = ref.loadUintBig(64);
64
+ const borrowRateSlopeLow = ref.loadUintBig(64);
65
+ const borrowRateSlopeHigh = ref.loadUintBig(64);
66
+ const supplyRateSlopeLow = ref.loadUintBig(64);
67
+ const supplyRateSlopeHigh = ref.loadUintBig(64);
68
+ const targetUtilization = ref.loadUintBig(64);
69
+ const originationFee = ref.loadUintBig(64);
70
+ const dust = ref.loadUintBig(64);
70
71
 
71
72
  return {
72
73
  oracle,
@@ -81,6 +82,7 @@ export function createAssetConfig(): DictionaryValue<AssetConfig> {
81
82
  supplyRateSlopeHigh,
82
83
  targetUtilization,
83
84
  originationFee,
85
+ dust,
84
86
  };
85
87
  },
86
88
  };
@@ -123,7 +125,7 @@ export function parseMasterData(masterDataBOC: string): MasterData {
123
125
  const masterConfig = {
124
126
  ifActive: masterConfigSlice.loadInt(8),
125
127
  admin: masterConfigSlice.loadAddress(),
126
- adminPK: masterConfigSlice.loadBuffer(64),
128
+ adminPK: masterConfigSlice.loadUintBig(256),
127
129
  tokenKeys: loadMaybeMyRef(masterConfigSlice),
128
130
  walletToMaster: loadMaybeMyRef(masterConfigSlice),
129
131
  };
package/src/api/prices.ts CHANGED
@@ -1,127 +1,70 @@
1
- import { beginCell, Cell, Dictionary } from '@ton/core';
2
- import { ethers } from 'ethers';
3
- import { CoinData } from '../types/Redstone';
4
- import { ASSET_ID } from '../constants';
5
- import { PriceData } from '../types/Common';
6
-
7
- type SerializedPrice = {
8
- symbol: string;
9
- value: number;
10
- timestamp: number;
11
- };
12
-
13
- type PriceRawData = {
14
- data: Buffer;
15
- signature: Buffer;
16
- dictKey: bigint;
17
- dictValue: bigint;
18
- };
19
-
20
- function hexToArrayBuffer(input: any) {
21
- if (typeof input !== 'string') {
22
- throw new TypeError('Expected input to be a string');
23
- }
24
- if (input.length % 2 !== 0) {
25
- throw new RangeError('Expected string to be an even number of characters');
26
- }
27
-
28
- if (input.startsWith('0x')) {
29
- input = input.slice(2);
30
- }
31
- const view = new Uint8Array(input.length / 2);
32
- for (let i = 0; i < input.length; i += 2) {
33
- view[i / 2] = parseInt(input.substring(i, i + 2), 16);
34
- }
35
- return Buffer.from(view.buffer);
36
- }
37
-
38
- function convertStringToBytes32String(str: string) {
39
- if (str.length > 31) {
40
- const bytes32StringLength = 32 * 2 + 2; // 32 bytes (each byte uses 2 symbols) + 0x
41
- if (str.length === bytes32StringLength && str.startsWith('0x')) {
42
- return str;
43
- } else {
44
- return ethers.utils.id(str);
45
- }
46
- } else {
47
- return ethers.utils.formatBytes32String(str);
48
- }
49
- }
50
-
51
- export function getLiteDataBytesString(priceData: SerializedPrice): string {
52
- let data = priceData.symbol.substr(2) + priceData.value.toString(16).padStart(64, '0');
53
-
54
- data += Math.ceil(priceData.timestamp / 1000)
55
- .toString(16)
56
- .padStart(64, '0');
57
- return data;
58
- }
59
-
60
- async function getPrice(symbol: string): Promise<PriceRawData> {
61
- const res = await fetch(`https://api.redstone.finance/prices?symbol=${symbol}&provider=redstone&limit=1`);
62
- const data = (await res.json()) as CoinData[];
63
- const price = data[0];
64
-
65
- const message = {
66
- symbol: convertStringToBytes32String(price.symbol),
67
- value: Math.round(price.value * 10 ** 8),
68
- timestamp: price.timestamp,
69
- };
70
-
71
- let dictKey: bigint;
72
- const dictValue = BigInt(message.value) * 10n;
73
- switch (message.symbol) {
74
- case '0x544f4e0000000000000000000000000000000000000000000000000000000000':
75
- dictKey = ASSET_ID.TON;
76
- break;
77
- case '0x5553445400000000000000000000000000000000000000000000000000000000':
78
- dictKey = ASSET_ID.jUSDT;
79
- break;
80
- case '0x5553444300000000000000000000000000000000000000000000000000000000':
81
- dictKey = ASSET_ID.jUSDC;
82
- break;
83
- default:
84
- throw new Error('Unknown symbol');
85
- }
86
-
87
- const signature = hexToArrayBuffer(price.liteEvmSignature);
88
-
89
- return {
90
- data: Buffer.from(getLiteDataBytesString(message), 'hex'),
91
- signature: signature,
92
- dictKey: dictKey,
93
- dictValue: dictValue,
94
- };
95
- }
96
-
97
- export async function getPrices(): Promise<PriceData | undefined> {
98
- try {
99
- const symbols = ['TON', 'USDT', 'USDC'];
100
- const rawPriceData: {
101
- data: Buffer;
102
- signature: Buffer;
103
- }[] = [];
104
- const priceDict = Dictionary.empty(Dictionary.Keys.BigUint(256), Dictionary.Values.BigUint(64));
105
- const pricePromises = symbols.map(async (symbol) => {
106
- const price = await getPrice(symbol);
107
- priceDict.set(price.dictKey, price.dictValue);
108
- rawPriceData.push(price);
109
- });
110
- await Promise.all(pricePromises);
111
-
112
- const rawPricesDict = Dictionary.empty<Buffer, Cell>();
113
- for (const data of rawPriceData) {
114
- rawPricesDict.set(data.signature, beginCell().storeBuffer(data.data).endCell());
115
- }
116
-
117
- return {
118
- dict: priceDict,
119
- dataCell: beginCell()
120
- .storeDictDirect(rawPricesDict, Dictionary.Keys.Buffer(65), Dictionary.Values.Cell())
121
- .endCell(),
122
- };
123
- } catch (error) {
124
- console.error(error);
125
- return undefined;
126
- }
127
- }
1
+ import { beginCell, Cell, Dictionary } from '@ton/core';
2
+ import { NFT_ID } from '../constants';
3
+ import { PriceData } from '../types/Common';
4
+
5
+ type NftData = {
6
+ ledgerIndex: number;
7
+ pageSize: number;
8
+ items: string[];
9
+ };
10
+
11
+ type OutputData = {
12
+ metadata: {
13
+ blockId: string;
14
+ transactionId: string;
15
+ outputIndex: number;
16
+ isSpent: boolean;
17
+ milestoneIndexSpent: number;
18
+ milestoneTimestampSpent: number;
19
+ transactionIdSpent: string;
20
+ milestoneIndexBooked: number;
21
+ milestoneTimestampBooked: number;
22
+ ledgerIndex: number;
23
+ };
24
+ output: {
25
+ type: number;
26
+ amount: string;
27
+ nftId: string;
28
+ unlockConditions: {
29
+ type: number;
30
+ address: {
31
+ type: number;
32
+ pubKeyHash: string;
33
+ };
34
+ }[];
35
+ features: {
36
+ type: number;
37
+ data: string;
38
+ }[];
39
+ };
40
+ };
41
+
42
+ export async function getPrices(): Promise<PriceData | undefined> {
43
+ try {
44
+ let result = await fetch('https://api.stardust-mainnet.iotaledger.net/api/indexer/v1/outputs/nft/' + NFT_ID, {
45
+ headers: { accept: 'application/json' },
46
+ });
47
+ let outputId = (await result.json()) as NftData;
48
+
49
+ result = await fetch('https://api.stardust-mainnet.iotaledger.net/api/core/v2/outputs/' + outputId.items[0], {
50
+ headers: { accept: 'application/json' },
51
+ });
52
+
53
+ let resData = (await result.json()) as OutputData;
54
+
55
+ const data = JSON.parse(
56
+ decodeURIComponent(resData.output.features[0].data.replace('0x', '').replace(/[0-9a-f]{2}/g, '%$&')),
57
+ );
58
+
59
+ const pricesCell = Cell.fromBoc(Buffer.from(data['packedPrices'], 'hex'))[0];
60
+ const signature = Buffer.from(data['signature'], 'hex');
61
+
62
+ return {
63
+ dict: pricesCell.beginParse().loadDictDirect(Dictionary.Keys.BigUint(256), Dictionary.Values.BigUint(64)),
64
+ dataCell: beginCell().storeRef(pricesCell).storeBuffer(signature).endCell(),
65
+ };
66
+ } catch (error) {
67
+ console.error(error);
68
+ return undefined;
69
+ }
70
+ }
package/src/constants.ts CHANGED
@@ -2,21 +2,26 @@ import { Address, Cell, toNano } from '@ton/core';
2
2
  import { sha256Hash } from './utils/sha256BigInt';
3
3
 
4
4
  export const EVAA_MASTER_MAINNET = Address.parse('EQC8rUZqR_pWV1BylWUlPNBzyiTYVoBEmQkMIQDZXICfnuRr');
5
- export const MAINNET_VERSION = 2;
6
- export const EVAA_MASTER_TESTNET = Address.parse('kQBi2jDaq_-Oi62V7u_j_Vr1We8EqC3h0jkhB4Gf4JW741vX');
7
- export const TESTNET_VERSION = 1;
5
+ export const MAINNET_VERSION = 3;
6
+ export const EVAA_MASTER_TESTNET = Address.parse('kQClWdMebpK90b6imEUreQJ4M3oz8Gqwd3xkVIowR8LDX98-');
7
+ export const TESTNET_VERSION = 3;
8
+
9
+ export const NFT_ID = '0xfb9874544d76ca49c5db9cc3e5121e4c018bc8a2fb2bfe8f2a38c5b9963492f5';
8
10
 
9
11
  export const ASSET_ID = {
10
12
  TON: sha256Hash('TON'),
11
13
  jUSDT: sha256Hash('jUSDT'),
12
14
  jUSDC: sha256Hash('jUSDC'),
15
+ stTON: sha256Hash('stTON'),
13
16
  };
14
17
 
15
18
  export const JETTON_MASTER_ADDRESSES = {
16
19
  jUSDT_MAINNET: Address.parse('EQBwbF0otxLyA3VrRjjC1q7i3G7LtoEpdyBjZEuNtrhC4drm'),
17
- jUSDT_TESTNET: Address.parse('kQAGvWIETv29VRXLBL3lugxdLeCZ3r7jcuUvqKeZpbcwiQo0'),
20
+ jUSDT_TESTNET: Address.parse('kQBtFVedUkg9Q7M5eMx_gxAdP5R7QCLR-3RCYQNrm_DZYr6Z'),
18
21
  jUSDC_MAINNET: Address.parse('EQCEHZi-CLX2ghdsNbY35umR1OFODG5ySHrtK6GItMdWv7dS'),
19
- jUSDC_TESTNET: Address.parse('kQCwj7zrRnBIYUhM7BShqupouNgubrdJUmmA3AAuPH9CK0Kj'),
22
+ jUSDC_TESTNET: Address.parse('kQCZWZD_rBZ1vrqF22aX4AZrU1a1q-YKZH_R2VlALoVNCvXd'),
23
+ stTON_MAINNET: Address.parse('EQBOn-1b-315ogeCl5lfPYW0ut6sjA2eq4LTdRv5vJJ1SsxX'),
24
+ stTON_TESTNET: Address.parse('kQCpm8ixF6STW7aidxn_Qkp4sR73msPlrduCeRZfo-Zu7dxt'),
20
25
  };
21
26
 
22
27
  export const MASTER_CONSTANTS = {
@@ -25,12 +25,13 @@ export type AssetConfig = {
25
25
  supplyRateSlopeHigh: bigint;
26
26
  targetUtilization: bigint;
27
27
  originationFee: bigint;
28
+ dust: bigint;
28
29
  };
29
30
 
30
31
  export type MasterConfig = {
31
32
  ifActive: number;
32
33
  admin: Address;
33
- adminPK: Buffer;
34
+ adminPK: bigint;
34
35
  tokenKeys: Cell | null;
35
36
  walletToMaster: Cell | null;
36
37
  };
@@ -1,34 +1,41 @@
1
- import { Address, beginCell, storeStateInit } from '@ton/core';
2
- import { ASSET_ID, JETTON_MASTER_ADDRESSES, JETTON_WALLET_CODE } from '../constants';
3
-
4
- export function getUserJettonWallet(ownerAddress: Address, assetID: bigint, network: 'mainnet' | 'testnet'): Address {
5
- const builder = beginCell().storeCoins(0).storeAddress(ownerAddress);
6
- switch (assetID) {
7
- case ASSET_ID.jUSDT:
8
- if (network === 'mainnet') {
9
- builder.storeAddress(JETTON_MASTER_ADDRESSES.jUSDT_MAINNET);
10
- } else {
11
- builder.storeAddress(JETTON_MASTER_ADDRESSES.jUSDT_TESTNET);
12
- }
13
- break;
14
- case ASSET_ID.jUSDC:
15
- if (network === 'mainnet') {
16
- builder.storeAddress(JETTON_MASTER_ADDRESSES.jUSDC_MAINNET);
17
- } else {
18
- builder.storeAddress(JETTON_MASTER_ADDRESSES.jUSDC_TESTNET);
19
- }
20
- break;
21
- default:
22
- throw new Error('Unsupported asset');
23
- }
24
- const data = builder.storeRef(JETTON_WALLET_CODE).endCell();
25
- const stateInit = beginCell()
26
- .store(
27
- storeStateInit({
28
- code: JETTON_WALLET_CODE,
29
- data: data,
30
- }),
31
- )
32
- .endCell();
33
- return new Address(0, stateInit.hash());
34
- }
1
+ import { Address, beginCell, storeStateInit } from '@ton/core';
2
+ import { ASSET_ID, JETTON_MASTER_ADDRESSES, JETTON_WALLET_CODE } from '../constants';
3
+
4
+ export function getUserJettonWallet(ownerAddress: Address, assetID: bigint, network: 'mainnet' | 'testnet'): Address {
5
+ const builder = beginCell().storeCoins(0).storeAddress(ownerAddress);
6
+ switch (assetID) {
7
+ case ASSET_ID.jUSDT:
8
+ if (network === 'mainnet') {
9
+ builder.storeAddress(JETTON_MASTER_ADDRESSES.jUSDT_MAINNET);
10
+ } else {
11
+ builder.storeAddress(JETTON_MASTER_ADDRESSES.jUSDT_TESTNET);
12
+ }
13
+ break;
14
+ case ASSET_ID.jUSDC:
15
+ if (network === 'mainnet') {
16
+ builder.storeAddress(JETTON_MASTER_ADDRESSES.jUSDC_MAINNET);
17
+ } else {
18
+ builder.storeAddress(JETTON_MASTER_ADDRESSES.jUSDC_TESTNET);
19
+ }
20
+ break;
21
+ case ASSET_ID.stTON:
22
+ if (network === 'mainnet') {
23
+ builder.storeAddress(JETTON_MASTER_ADDRESSES.stTON_MAINNET);
24
+ } else {
25
+ builder.storeAddress(JETTON_MASTER_ADDRESSES.stTON_TESTNET);
26
+ }
27
+ break;
28
+ default:
29
+ throw new Error('Unsupported asset');
30
+ }
31
+ const data = builder.storeRef(JETTON_WALLET_CODE).endCell();
32
+ const stateInit = beginCell()
33
+ .store(
34
+ storeStateInit({
35
+ code: JETTON_WALLET_CODE,
36
+ data: data,
37
+ }),
38
+ )
39
+ .endCell();
40
+ return new Address(0, stateInit.hash());
41
+ }
@@ -1,15 +0,0 @@
1
- export type CoinData = {
2
- id: string;
3
- symbol: string;
4
- provider: string;
5
- value: number;
6
- liteEvmSignature: string;
7
- permawebTx: string;
8
- version: string;
9
- source: {
10
- coingecko: number;
11
- };
12
- timestamp: number;
13
- minutes: number;
14
- providerPublicKey: string;
15
- };