From ad074d8c39e0d3293c188ecf8861a8ce73bd8c55 Mon Sep 17 00:00:00 2001 From: Matias Poblete <86752543+MattPoblete@users.noreply.github.com> Date: Mon, 23 Sep 2024 15:06:17 -0300 Subject: [PATCH 1/5] =?UTF-8?q?=E2=9C=A8Add=20fees=20to=20phoenix=20pairs?= =?UTF-8?q?=20tables?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- programs/phoenix/src/lib.rs | 3 +++ programs/phoenix/zephyr.toml | 6 +++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/programs/phoenix/src/lib.rs b/programs/phoenix/src/lib.rs index 1f96a6e..31fc619 100644 --- a/programs/phoenix/src/lib.rs +++ b/programs/phoenix/src/lib.rs @@ -9,6 +9,7 @@ struct PairsTable { token_b: ScVal, reserve_a: ScVal, reserve_b: ScVal, + fee: ScVal } //Phoenix Factory @@ -91,6 +92,7 @@ pub extern "C" fn on_close() { reserve_b: env.to_scval(0), token_a: env.to_scval("0"), token_b: env.to_scval("0"), + fee: env.to_scval(1) }; for entry in pair_entries { @@ -101,6 +103,7 @@ pub extern "C" fn on_close() { table.token_a = env.to_scval(config_data.token_a.to_string()); table.token_b = env.to_scval(config_data.token_b.to_string()); + table.fee = env.to_scval(config_data.total_fee_bps); } if entry.key == env.to_scval(PairDataKey::ReserveA){ diff --git a/programs/phoenix/zephyr.toml b/programs/phoenix/zephyr.toml index 963eb38..f6c2df1 100644 --- a/programs/phoenix/zephyr.toml +++ b/programs/phoenix/zephyr.toml @@ -24,4 +24,8 @@ col_type = "BYTEA" [[tables.columns]] name = "reserve_b" -col_type = "BYTEA" \ No newline at end of file +col_type = "BYTEA" + +[[tables.columns]] +name = "fee" +col_type = "BYTEA" From 1d99c0ae86bdd195af4dffb72b62d31091af8f59 Mon Sep 17 00:00:00 2001 From: Matias Poblete <86752543+MattPoblete@users.noreply.github.com> Date: Tue, 24 Sep 2024 08:10:55 -0300 Subject: [PATCH 2/5] =?UTF-8?q?=E2=9C=A8Add=20aqua=20fees=20to=20zephyr=20?= =?UTF-8?q?tables?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- programs/aqua/src/lib.rs | 14 +++++++++----- programs/aqua/zephyr.toml | 4 ++++ 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/programs/aqua/src/lib.rs b/programs/aqua/src/lib.rs index d121ce8..01ab20b 100644 --- a/programs/aqua/src/lib.rs +++ b/programs/aqua/src/lib.rs @@ -26,6 +26,7 @@ struct PairsTable { token_b: ScVal, reserve_a: ScVal, reserve_b: ScVal, + fee: ScVal } #[no_mangle] @@ -37,7 +38,6 @@ pub extern "C" fn on_close() { let lp_router_contract = stellar_strkey::Contract::from_string(&contract_address_str).unwrap().0; let rows = env.read::(); - env.log().debug(format!("rows: {:?}", &rows), None); let lp_router_contract_events: Vec = { let events = env.reader().pretty().soroban_events(); @@ -54,8 +54,6 @@ pub extern "C" fn on_close() { }; for t_event in lp_router_contract_events { - env.log().debug(format!("event: {:?}", &t_event), None); - let action: Symbol = env.from_scval(&t_event.topics[0]); let tokens: SorobanVec
= env.from_scval(&t_event.topics[1]); @@ -88,6 +86,7 @@ pub extern "C" fn on_close() { reserve_b: env.to_scval(0), token_a: env.to_scval(tokens.first()), token_b: env.to_scval(tokens.last()), + fee: env.to_scval(0) }; env.log().debug(format!("New action Table: {:?}", table), None); @@ -119,6 +118,7 @@ pub(crate) fn handle_add(env: &EnvClient, event: &PrettyContractEvent, data_leng let mut reserve_a: u128 = 0; let mut reserve_b: u128 = 0; + let mut fee_fraction: u32 = 0; if let Some(instance) = instance_storage { if let LedgerEntryData::ContractData(contract_data_entry) = &instance.entry.data { @@ -126,7 +126,6 @@ pub(crate) fn handle_add(env: &EnvClient, event: &PrettyContractEvent, data_leng if let Some(storage_map) = &contract_instance.storage { for entry in storage_map.iter() { - if let ScVal::Vec(Some(vec)) = &entry.key { if let Some(ScVal::Symbol(symbol)) = vec.first() { @@ -140,8 +139,12 @@ pub(crate) fn handle_add(env: &EnvClient, event: &PrettyContractEvent, data_leng env.log().debug(format!("ReseveB: {:?}", entry), None); reserve_b = parts.lo.into() } + } else if symbol.to_string() == "FeeFraction" { + if let ScVal::U32(fee) = &entry.val { + env.log().debug(format!("FeeFraction: {:?}", entry), None); + fee_fraction = fee.clone() + } } - } } } @@ -159,6 +162,7 @@ pub(crate) fn handle_add(env: &EnvClient, event: &PrettyContractEvent, data_leng reserve_b: env.to_scval(reserve_b), token_a: env.to_scval(tokens.first()), token_b: env.to_scval(tokens.last()), + fee: env.to_scval(fee_fraction) }; env.log().debug(format!("New action Table: {:?}", table), None); diff --git a/programs/aqua/zephyr.toml b/programs/aqua/zephyr.toml index 2e9fb7e..b55a7de 100644 --- a/programs/aqua/zephyr.toml +++ b/programs/aqua/zephyr.toml @@ -24,4 +24,8 @@ col_type = "BYTEA" [[tables.columns]] name = "reserve_b" +col_type = "BYTEA" + +[[tables.columns]] +name = "fee" col_type = "BYTEA" \ No newline at end of file From 625857e40fe5bbcb6a16dd1d312d8158b4bf1943 Mon Sep 17 00:00:00 2001 From: Matias Poblete <86752543+MattPoblete@users.noreply.github.com> Date: Tue, 24 Sep 2024 08:41:54 -0300 Subject: [PATCH 3/5] =?UTF-8?q?=F0=9F=A9=B9A=20wrongly=20declared=20variab?= =?UTF-8?q?le=20was=20corrected.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- programs/phoenix/src/lib.rs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/programs/phoenix/src/lib.rs b/programs/phoenix/src/lib.rs index 31fc619..cd488e9 100644 --- a/programs/phoenix/src/lib.rs +++ b/programs/phoenix/src/lib.rs @@ -92,7 +92,7 @@ pub extern "C" fn on_close() { reserve_b: env.to_scval(0), token_a: env.to_scval("0"), token_b: env.to_scval("0"), - fee: env.to_scval(1) + fee: env.to_scval(0) }; for entry in pair_entries { @@ -121,14 +121,9 @@ pub extern "C" fn on_close() { }else{ table.put(&env); } - }); } - } - - - } From dd7a701bc2fcc2318fc06151e16e17fcda747d75 Mon Sep 17 00:00:00 2001 From: Matias Poblete <86752543+MattPoblete@users.noreply.github.com> Date: Fri, 27 Sep 2024 10:17:13 -0300 Subject: [PATCH 4/5] =?UTF-8?q?=F0=9F=9A=A7=F0=9F=A7=AA=20updating=20pairs?= =?UTF-8?q?=20tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/__tests__/pairs.test.ts | 29 +++++++++++++++++------ scripts/utils/get-fees-from-pair.ts | 35 ++++++++++++++++++++++++++++ scripts/utils/get-pairs.ts | 36 +++++++++++++++++++++++++++++ scripts/utils/tx.ts | 5 +++- 4 files changed, 97 insertions(+), 8 deletions(-) create mode 100644 scripts/utils/get-fees-from-pair.ts diff --git a/scripts/__tests__/pairs.test.ts b/scripts/__tests__/pairs.test.ts index 1fe637c..79d1fc6 100644 --- a/scripts/__tests__/pairs.test.ts +++ b/scripts/__tests__/pairs.test.ts @@ -1,12 +1,13 @@ // import fs from "fs"; import { zephyrTableToGraphQLParser} from "mercury-sdk"; -import { getPairs } from "../utils/get-pairs"; +import { getAquaPairs, getPairs } from "../utils/get-pairs"; import { getTotalPairs } from "../utils/get-total-pairs"; import { getZephyrTable } from "../utils/get-table"; import fs from "fs"; +import { getFeesFromPair } from "../utils/get-fees-from-pair"; -test("soroswap pairs in MAINNET return non empty array", async () => { +test.skip("soroswap pairs in MAINNET return non empty array", async () => { let soroswapPairsTable = getZephyrTable('soroswap_pairs', "MAINNET") const zephyrTableGraphQL = zephyrTableToGraphQLParser(soroswapPairsTable); const pairs = await getPairs(zephyrTableGraphQL.address, 'MAINNET'); @@ -15,7 +16,7 @@ test("soroswap pairs in MAINNET return non empty array", async () => { // console.log("🚀 ~ test ~ Soroswap mainnet pairs.length:", pairs.length) }); -test("soroswap pairs in MAINNET amount is equal to Factory all_pairs_length()", async () => { +test.skip("soroswap pairs in MAINNET amount is equal to Factory all_pairs_length()", async () => { let soroswapPairsTable = getZephyrTable('soroswap_pairs', "MAINNET") const zephyrTableGraphQL = zephyrTableToGraphQLParser(soroswapPairsTable); const pairs = await getPairs(zephyrTableGraphQL.address, 'MAINNET'); @@ -23,7 +24,7 @@ test("soroswap pairs in MAINNET amount is equal to Factory all_pairs_length()", expect(pairs.length).toEqual(totalPairs); }); -test("soroswap pairs in TESTNET return non empty array", async () => { +test.skip("soroswap pairs in TESTNET return non empty array", async () => { let soroswapPairsTable = getZephyrTable('soroswap_pairs', "TESTNET") const zephyrTableGraphQL = zephyrTableToGraphQLParser(soroswapPairsTable); const pairs = await getPairs(zephyrTableGraphQL.address, 'TESTNET'); @@ -33,7 +34,7 @@ test("soroswap pairs in TESTNET return non empty array", async () => { }); -test("soroswap pairs in TESTNET amount is equal to Factory all_pairs_length()", async () => { +test.skip("soroswap pairs in TESTNET amount is equal to Factory all_pairs_length()", async () => { let soroswapPairsTable = getZephyrTable('soroswap_pairs', "TESTNET") // console.log("using table ", soroswapPairsTable) const zephyrTableGraphQL = zephyrTableToGraphQLParser(soroswapPairsTable); @@ -52,10 +53,24 @@ test.todo("aqua pairs in TESTNET return non empty array"); test.todo("aqua pairs in TESTNET is equal to Factory all_pairs_length()"); test.todo("aqua pairs in MAINNET return non empty array"); +test("aqua pairs in MAINNET amount is greater than 0", async () => { + const aquaPairsTable = getZephyrTable('aqua_pairs', "MAINNET") + const zephyrTableGraphQL = zephyrTableToGraphQLParser(aquaPairsTable); + const pairs = await getAquaPairs(zephyrTableGraphQL.address, 'MAINNET'); + console.log('🟡Pairs', pairs) + for(let pair of pairs){ + const address = pair.address; + const fee = pair.fee; + console.log('🟡address', address) + console.log('🟡fee', fee) + const blockchainFees = await getFeesFromPair('aqua', 'MAINNET', address) + console.log('🟡blockchainFees', blockchainFees) + } +}); test.todo("aqua pairs in MAINNET is equal to Factory all_pairs_length()"); -test("phoenix pairs in MAINNET return non empty array", async () => { +test.skip("phoenix pairs in MAINNET return non empty array", async () => { let phoenixPairsTable = getZephyrTable('phoenix_pairs', "MAINNET") const zephyrTableGraphQL = zephyrTableToGraphQLParser(phoenixPairsTable); const pairs = await getPairs(zephyrTableGraphQL.address, 'MAINNET'); @@ -64,7 +79,7 @@ test("phoenix pairs in MAINNET return non empty array", async () => { // console.log("🚀 ~ test ~ phoenix mainnet pairs.length:", pairs.length) }); -test("phoenix pairs in TESTNET return non empty array", async () => { +test.skip("phoenix pairs in TESTNET return non empty array", async () => { let phoenixPairsTable = getZephyrTable('phoenix_pairs', "TESTNET") const zephyrTableGraphQL = zephyrTableToGraphQLParser(phoenixPairsTable); const pairs = await getPairs(zephyrTableGraphQL.address, 'TESTNET'); diff --git a/scripts/utils/get-fees-from-pair.ts b/scripts/utils/get-fees-from-pair.ts new file mode 100644 index 0000000..266c563 --- /dev/null +++ b/scripts/utils/get-fees-from-pair.ts @@ -0,0 +1,35 @@ +import {scValToNative} from "@stellar/stellar-sdk" +import {invokeCustomContract} from "./contract"; +import { config } from './env_config'; + + +// import * as StellarSdk from "@stellar/stellar-sdk"; + +export const getFeesFromPair = async ( + protocolName: string, + network: "MAINNET" | "TESTNET", + pairAddress: string) => { + + let loadedConfig; + if (network === "MAINNET") { + loadedConfig = config('mainnet'); + } else { + loadedConfig = config('testnet'); + } + + const reserves = await invokeCustomContract( + pairAddress, + "get_fee_fraction", + [], + loadedConfig.user, + loadedConfig, + true); + // console.log("🚀 ~ getFeesFromPair ~ reserves", reserves.result.retval) + const reservesNative=scValToNative(reserves.result.retval) + console.log(reservesNative) + // console.log("🚀 ~ reservesNative:", reservesNative) + // const totalPairsNative=scValToNative(totalPairs.result.retval) + + return reservesNative; + +}; diff --git a/scripts/utils/get-pairs.ts b/scripts/utils/get-pairs.ts index 6d1473c..1a7147a 100644 --- a/scripts/utils/get-pairs.ts +++ b/scripts/utils/get-pairs.ts @@ -5,6 +5,7 @@ interface Pair { tokenA: string; tokenB: string; address: string; + fee?: number; } const parseValue = (value: any) => { @@ -44,3 +45,38 @@ export const getPairs = async (tableName: string, network: "MAINNET" | "TESTNET" return []; }; +export const getAquaPairs = async (tableName: string, network: "MAINNET" | "TESTNET") => { + + const mercuryInstance = getMercuryInstance(network); + const res = await mercuryInstance.getCustomQuery({ + request: `query Query { + events: allZephyr3B2F44Dfcda9Ebf57D4Deb257E6D4E90S { + data: nodes { + address + tokenA + tokenB + reserveA + reserveB + fee + } + } + }`, + }); + + console.log('res', res) + if (res.ok) { + const pairs = res.data.events.data.map((d: any) => { + let n: any = {}; + + for (let key in d) { + n[key] = parseValue(d[key]); + } + + return n; + }); + + return pairs as Pair[]; + } + + return []; +}; diff --git a/scripts/utils/tx.ts b/scripts/utils/tx.ts index 817a6bc..e442f6d 100644 --- a/scripts/utils/tx.ts +++ b/scripts/utils/tx.ts @@ -1,5 +1,6 @@ import { Account, Keypair, SorobanRpc, Transaction, TransactionBuilder, xdr } from '@stellar/stellar-sdk'; import { EnvConfig } from './env_config.js'; +import { AxiosClient } from '@stellar/stellar-sdk/rpc'; type txResponse = SorobanRpc.Api.SendTransactionResponse | SorobanRpc.Api.GetTransactionResponse; type txStatus = SorobanRpc.Api.SendTransactionStatus | SorobanRpc.Api.GetTransactionStatus; @@ -21,6 +22,7 @@ export async function invoke( loadedConfig: EnvConfig, sim: boolean ): Promise { + console.log('🟡invoking custom contract') const txBuilder = await createTxBuilder(source, loadedConfig); if (typeof operation === 'string') { operation = xdr.Operation.fromXDR(operation, 'base64'); @@ -33,8 +35,9 @@ export async function invoke( } export async function createTxBuilder(source: Keypair, loadedConfig: EnvConfig): Promise { + console.log(source.publicKey()) try { - const account: Account = await loadedConfig.rpc.getAccount(source.publicKey()); + const account: Account = await AxiosClient.get(`https://horizon.stellar.org/accounts/${source.publicKey()}`); return new TransactionBuilder(account, { fee: '10000', timebounds: { minTime: 0, maxTime: 0 }, From d585b07746c6f40bbf4179d8ea6662f549dd1575 Mon Sep 17 00:00:00 2001 From: Matias Poblete <86752543+MattPoblete@users.noreply.github.com> Date: Mon, 30 Sep 2024 13:04:57 -0300 Subject: [PATCH 5/5] =?UTF-8?q?=F0=9F=9A=A7=F0=9F=A7=AARemove=20workaround?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/__tests__/pairs.test.ts | 8 +++----- scripts/utils/get-pairs.ts | 1 - scripts/utils/tx.ts | 4 +--- 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/scripts/__tests__/pairs.test.ts b/scripts/__tests__/pairs.test.ts index b18b69b..5419003 100644 --- a/scripts/__tests__/pairs.test.ts +++ b/scripts/__tests__/pairs.test.ts @@ -58,14 +58,12 @@ test("aqua pairs in MAINNET amount is greater than 0", async () => { const aquaPairsTable = getZephyrTable('aqua_pairs', "MAINNET") const zephyrTableGraphQL = zephyrTableToGraphQLParser(aquaPairsTable); const pairs = await getAquaPairs(zephyrTableGraphQL.address, 'MAINNET'); - console.log('🟡Pairs', pairs) for(let pair of pairs){ const address = pair.address; const fee = pair.fee; - console.log('🟡address', address) - console.log('🟡fee', fee) - const blockchainFees = await getFeesFromPair('aqua', 'MAINNET', address) - console.log('🟡blockchainFees', blockchainFees) + const blockchainFee = await getFeesFromPair('aqua', 'MAINNET', address) + console.log('🟡blockchainFee', blockchainFee) + //To do: check if blockchainFee are equal to fee } }); test.todo("aqua pairs in MAINNET is equal to Factory all_pairs_length()"); diff --git a/scripts/utils/get-pairs.ts b/scripts/utils/get-pairs.ts index 743df35..1b2870c 100644 --- a/scripts/utils/get-pairs.ts +++ b/scripts/utils/get-pairs.ts @@ -65,7 +65,6 @@ export const getAquaPairs = async (tableName: string, network: "MAINNET" | "TEST }`, }); - console.log('res', res) if (res.ok) { const pairs = res.data.events.data.map((d: any) => { let n: any = {}; diff --git a/scripts/utils/tx.ts b/scripts/utils/tx.ts index e442f6d..298938a 100644 --- a/scripts/utils/tx.ts +++ b/scripts/utils/tx.ts @@ -22,7 +22,6 @@ export async function invoke( loadedConfig: EnvConfig, sim: boolean ): Promise { - console.log('🟡invoking custom contract') const txBuilder = await createTxBuilder(source, loadedConfig); if (typeof operation === 'string') { operation = xdr.Operation.fromXDR(operation, 'base64'); @@ -35,9 +34,8 @@ export async function invoke( } export async function createTxBuilder(source: Keypair, loadedConfig: EnvConfig): Promise { - console.log(source.publicKey()) try { - const account: Account = await AxiosClient.get(`https://horizon.stellar.org/accounts/${source.publicKey()}`); + const account: Account = await loadedConfig.rpc.getAccount(source.publicKey()); return new TransactionBuilder(account, { fee: '10000', timebounds: { minTime: 0, maxTime: 0 },