Type/to search
8
Follow
1364
Followers
Платформа FMZ Web3 Ethereum Practice - Обмен заказами на основе смарт-контракта
Discussions
Created 2025-03-17 11:00:33  Updated 2025-03-18 15:54:46
 0
 883

img

Предисловие

На рынке криптовалют торговые возможности мимолетны, особенно окна высокодоходного арбитража, которые часто длятся очень короткое время. Если вы полагаетесь исключительно на ручную торговлю, вам часто бывает сложно угнаться за рынком. Таким образом, торговля отложенными ордерами становится важным средством повышения эффективности торговли.

Эта статья основана на идеях статьи Xiaocao. Она реконструирует стратегию торгового пула Curve.fi на платформе FMZ и знакомит с тем, как достичь того же эффекта через платформу FMZ. В то же время будет подробно рассмотрена схема защиты закрытого ключа для обеспечения как безопасности, так и удобства в процессе программной торговли.

Стратегия написана на JavaScript и использует объект обмена web3 eth платформы FMZ.

Безопасность заложена в конструкцию

На основе статьи「Как реализовать размещение заказов на децентрализованных биржах — на примере Curve」В проекте безопасности мы используем аналогичный метод шифрования AES. Для шифрования данных мы используем пароль и счетчик.

  • Пароль: пароль, хешированный с помощью sha256.
  • Подсчет: подсчет, использование временной метки в качестве случайного подсчета для участия в шифровании.
  1. Зашифруйте закрытый ключ в автономном режиме, используйте «пароль» и «количество» для шифрования закрытого ключа и получите зашифрованный секретный ключ.
  2. Настройте зашифрованный ключ, пароль, счетчик и т. д. для платформы FMZ и используйте параметр интерфейса политики "Зашифрованная строка". Содержимое, введенное в элемент управления, будет зашифровано, а информация о конфигурации, записанная на платформе, не является простым текстовым содержимым в элементе управления.
  3. Когда стратегия запущена, хранитель может расшифровать информацию и загрузить секретный ключ (после загрузки секретного ключа все связанные переменные будут сброшены).

img

javascript
// 加密/解密方式 function cryptoKey(type, data, passWord, count) { // 加载加密库 eval(HttpQuery("https://cdnjs.cloudflare.com/ajax/libs/aes-js/3.1.2/index.min.js")) // sha256 密码 var hash = Encode("sha256", "string", "hex", passWord).substring(0, 32) if (type == "encrypt") { var key = aesjs.utils.utf8.toBytes(hash.substring(0, 32)) var counter = new aesjs.Counter(count) var textBytes = aesjs.utils.utf8.toBytes(data) var aesCtr = new aesjs.ModeOfOperation.ctr(key, counter) var encryptedBytes = aesCtr.encrypt(textBytes) var encryptedHex = aesjs.utils.hex.fromBytes(encryptedBytes) return encryptedHex } else if (type == "decrypt") { var key = aesjs.utils.utf8.toBytes(hash.substring(0, 32)) var counter = new aesjs.Counter(count) var aesCtrDecrypt = new aesjs.ModeOfOperation.ctr(key, counter) const decryptedBytes = aesCtrDecrypt.decrypt(aesjs.utils.hex.toBytes(data)) const decryptedText = aesjs.utils.utf8.fromBytes(decryptedBytes) return decryptedText } else { throw "function cryptoKey(), param 'type' not support" } }

Настроить объект обмена web3

https://www.fmz.com/m/platforms/add

img

В сети доступно множество узлов Ethereum, наиболее часто используемые из них:

Вы можете подать заявку на создание собственного адреса, а затем настроить его для использования. Я не буду вдаваться в подробности. Ключевую информацию вы можете заполнить по желанию. Мы планируем загружать ее динамически, поэтому нет смысла настраивать ее здесь.

javascript
exchange.IO("key", cryptoKey(descCryptoType[cryptoType], keyData, password, count)) walletAddress = exchange.IO("address") Log("载入秘钥,钱包地址:", walletAddress)

Используйте функцию exchange.IO("key", ...), инкапсулированную платформой, для загрузки и обновления закрытого ключа после расшифровки.

Регистрация ABI

После решения проблемы безопасности следующим шагом станет выполнение некоторых операций над смарт-контрактом Ethereum. Согласно Curve.fi DEX, упомянутому Xiaocao, мы можем легко найти это dApp в сети:

https://curve.fi/dex/ethereum/pools/factory-stable-ng-102/deposit/

На странице биржевого пула sDAI/sUSDe вы можете найти адрес контракта биржевого пула и ознакомиться с контрактом. Методы, которые мы можем использовать:

  • монеты: получить адрес контракта токена, участвующего в транзакции в пуле
  • get_dy: Рассчитать текущее количество обмена в пуле.
  • обмен: выполнить обмен.

Для вызова этих методов вам нужно сначала зарегистрировать ABI контракта пула. Я не фильтровал используемые методы, а просто скопировал и вставил полный ABI, а затем зарегистрировал его:

javascript
// sDAI/sUSDe 池合约地址和ABI var poolAddress = "0x167478921b907422F8E88B43C4Af2B8BEa278d3A" // 合约ABI var poolABI = `[{"name":"Transfer","inputs":[{"name":"sender","type":"address","indexed":true},{"name":"receiver","type":"address","indexed":true},{"name":"value","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"Approval","inputs":[{"name":"owner","type":"address","indexed":true},{"name":"spender","type":"address","indexed":true},{"name":"value","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"TokenExchange","inputs":[{"name":"buyer","type":"address","indexed":true},{"name":"sold_id","type":"int128","indexed":false},{"name":"tokens_sold","type":"uint256","indexed":false},{"name":"bought_id","type":"int128","indexed":false},{"name":"tokens_bought","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"TokenExchangeUnderlying","inputs":[{"name":"buyer","type":"address","indexed":true},{"name":"sold_id","type":"int128","indexed":false},{"name":"tokens_sold","type":"uint256","indexed":false},{"name":"bought_id","type":"int128","indexed":false},{"name":"tokens_bought","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"AddLiquidity","inputs":[{"name":"provider","type":"address","indexed":true},{"name":"token_amounts","type":"uint256[]","indexed":false},{"name":"fees","type":"uint256[]","indexed":false},{"name":"invariant","type":"uint256","indexed":false},{"name":"token_supply","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"RemoveLiquidity","inputs":[{"name":"provider","type":"address","indexed":true},{"name":"token_amounts","type":"uint256[]","indexed":false},{"name":"fees","type":"uint256[]","indexed":false},{"name":"token_supply","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"RemoveLiquidityOne","inputs":[{"name":"provider","type":"address","indexed":true},{"name":"token_id","type":"int128","indexed":false},{"name":"token_amount","type":"uint256","indexed":false},{"name":"coin_amount","type":"uint256","indexed":false},{"name":"token_supply","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"RemoveLiquidityImbalance","inputs":[{"name":"provider","type":"address","indexed":true},{"name":"token_amounts","type":"uint256[]","indexed":false},{"name":"fees","type":"uint256[]","indexed":false},{"name":"invariant","type":"uint256","indexed":false},{"name":"token_supply","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"RampA","inputs":[{"name":"old_A","type":"uint256","indexed":false},{"name":"new_A","type":"uint256","indexed":false},{"name":"initial_time","type":"uint256","indexed":false},{"name":"future_time","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"StopRampA","inputs":[{"name":"A","type":"uint256","indexed":false},{"name":"t","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"ApplyNewFee","inputs":[{"name":"fee","type":"uint256","indexed":false},{"name":"offpeg_fee_multiplier","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"SetNewMATime","inputs":[{"name":"ma_exp_time","type":"uint256","indexed":false},{"name":"D_ma_time","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"stateMutability":"nonpayable","type":"constructor","inputs":[{"name":"_name","type":"string"},{"name":"_symbol","type":"string"},{"name":"_A","type":"uint256"},{"name":"_fee","type":"uint256"},{"name":"_offpeg_fee_multiplier","type":"uint256"},{"name":"_ma_exp_time","type":"uint256"},{"name":"_coins","type":"address[]"},{"name":"_rate_multipliers","type":"uint256[]"},{"name":"_asset_types","type":"uint8[]"},{"name":"_method_ids","type":"bytes4[]"},{"name":"_oracles","type":"address[]"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"exchange","inputs":[{"name":"i","type":"int128"},{"name":"j","type":"int128"},{"name":"_dx","type":"uint256"},{"name":"_min_dy","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"exchange","inputs":[{"name":"i","type":"int128"},{"name":"j","type":"int128"},{"name":"_dx","type":"uint256"},{"name":"_min_dy","type":"uint256"},{"name":"_receiver","type":"address"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"exchange_received","inputs":[{"name":"i","type":"int128"},{"name":"j","type":"int128"},{"name":"_dx","type":"uint256"},{"name":"_min_dy","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"exchange_received","inputs":[{"name":"i","type":"int128"},{"name":"j","type":"int128"},{"name":"_dx","type":"uint256"},{"name":"_min_dy","type":"uint256"},{"name":"_receiver","type":"address"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"add_liquidity","inputs":[{"name":"_amounts","type":"uint256[]"},{"name":"_min_mint_amount","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"add_liquidity","inputs":[{"name":"_amounts","type":"uint256[]"},{"name":"_min_mint_amount","type":"uint256"},{"name":"_receiver","type":"address"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"remove_liquidity_one_coin","inputs":[{"name":"_burn_amount","type":"uint256"},{"name":"i","type":"int128"},{"name":"_min_received","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"remove_liquidity_one_coin","inputs":[{"name":"_burn_amount","type":"uint256"},{"name":"i","type":"int128"},{"name":"_min_received","type":"uint256"},{"name":"_receiver","type":"address"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"remove_liquidity_imbalance","inputs":[{"name":"_amounts","type":"uint256[]"},{"name":"_max_burn_amount","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"remove_liquidity_imbalance","inputs":[{"name":"_amounts","type":"uint256[]"},{"name":"_max_burn_amount","type":"uint256"},{"name":"_receiver","type":"address"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"remove_liquidity","inputs":[{"name":"_burn_amount","type":"uint256"},{"name":"_min_amounts","type":"uint256[]"}],"outputs":[{"name":"","type":"uint256[]"}]},{"stateMutability":"nonpayable","type":"function","name":"remove_liquidity","inputs":[{"name":"_burn_amount","type":"uint256"},{"name":"_min_amounts","type":"uint256[]"},{"name":"_receiver","type":"address"}],"outputs":[{"name":"","type":"uint256[]"}]},{"stateMutability":"nonpayable","type":"function","name":"remove_liquidity","inputs":[{"name":"_burn_amount","type":"uint256"},{"name":"_min_amounts","type":"uint256[]"},{"name":"_receiver","type":"address"},{"name":"_claim_admin_fees","type":"bool"}],"outputs":[{"name":"","type":"uint256[]"}]},{"stateMutability":"nonpayable","type":"function","name":"withdraw_admin_fees","inputs":[],"outputs":[]},{"stateMutability":"view","type":"function","name":"last_price","inputs":[{"name":"i","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"ema_price","inputs":[{"name":"i","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"get_p","inputs":[{"name":"i","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"price_oracle","inputs":[{"name":"i","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"D_oracle","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"transfer","inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"outputs":[{"name":"","type":"bool"}]},{"stateMutability":"nonpayable","type":"function","name":"transferFrom","inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"outputs":[{"name":"","type":"bool"}]},{"stateMutability":"nonpayable","type":"function","name":"approve","inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"outputs":[{"name":"","type":"bool"}]},{"stateMutability":"nonpayable","type":"function","name":"permit","inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"},{"name":"_deadline","type":"uint256"},{"name":"_v","type":"uint8"},{"name":"_r","type":"bytes32"},{"name":"_s","type":"bytes32"}],"outputs":[{"name":"","type":"bool"}]},{"stateMutability":"view","type":"function","name":"DOMAIN_SEPARATOR","inputs":[],"outputs":[{"name":"","type":"bytes32"}]},{"stateMutability":"view","type":"function","name":"get_dx","inputs":[{"name":"i","type":"int128"},{"name":"j","type":"int128"},{"name":"dy","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"get_dy","inputs":[{"name":"i","type":"int128"},{"name":"j","type":"int128"},{"name":"dx","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"calc_withdraw_one_coin","inputs":[{"name":"_burn_amount","type":"uint256"},{"name":"i","type":"int128"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"totalSupply","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"get_virtual_price","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"calc_token_amount","inputs":[{"name":"_amounts","type":"uint256[]"},{"name":"_is_deposit","type":"bool"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"A","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"A_precise","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"balances","inputs":[{"name":"i","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"get_balances","inputs":[],"outputs":[{"name":"","type":"uint256[]"}]},{"stateMutability":"view","type":"function","name":"stored_rates","inputs":[],"outputs":[{"name":"","type":"uint256[]"}]},{"stateMutability":"view","type":"function","name":"dynamic_fee","inputs":[{"name":"i","type":"int128"},{"name":"j","type":"int128"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"ramp_A","inputs":[{"name":"_future_A","type":"uint256"},{"name":"_future_time","type":"uint256"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"stop_ramp_A","inputs":[],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"set_new_fee","inputs":[{"name":"_new_fee","type":"uint256"},{"name":"_new_offpeg_fee_multiplier","type":"uint256"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"set_ma_exp_time","inputs":[{"name":"_ma_exp_time","type":"uint256"},{"name":"_D_ma_time","type":"uint256"}],"outputs":[]},{"stateMutability":"view","type":"function","name":"N_COINS","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"coins","inputs":[{"name":"arg0","type":"uint256"}],"outputs":[{"name":"","type":"address"}]},{"stateMutability":"view","type":"function","name":"fee","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"offpeg_fee_multiplier","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"admin_fee","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"initial_A","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"future_A","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"initial_A_time","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"future_A_time","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"admin_balances","inputs":[{"name":"arg0","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"ma_exp_time","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"D_ma_time","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"ma_last_time","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"name","inputs":[],"outputs":[{"name":"","type":"string"}]},{"stateMutability":"view","type":"function","name":"symbol","inputs":[],"outputs":[{"name":"","type":"string"}]},{"stateMutability":"view","type":"function","name":"decimals","inputs":[],"outputs":[{"name":"","type":"uint8"}]},{"stateMutability":"view","type":"function","name":"version","inputs":[],"outputs":[{"name":"","type":"string"}]},{"stateMutability":"view","type":"function","name":"balanceOf","inputs":[{"name":"arg0","type":"address"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"allowance","inputs":[{"name":"arg0","type":"address"},{"name":"arg1","type":"address"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"nonces","inputs":[{"name":"arg0","type":"address"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"salt","inputs":[],"outputs":[{"name":"","type":"bytes32"}]}]` // 注册ABI exchange.IO("abi", poolAddress, poolABI)

Прочитать баланс кошелька и баланс токенов

Чтение баланса токена кошелька, точности токена, имени токена и т. д. — все это методы контрактов ERC20 и регистрируются по умолчанию.

javascript
var token0Name = exchange.IO("api", token0Address, "symbol") var token1Name = exchange.IO("api", token1Address, "symbol") var token0Decimals = exchange.IO("api", token0Address, "decimals") var token1Decimals = exchange.IO("api", token1Address, "decimals")
javascript
var sDAI_Balance = exchange.IO("api", sDAI["address"], "balanceOf", walletAddress) var sUSDe_Balance = exchange.IO("api", sUSDe["address"], "balanceOf", walletAddress)

Мониторинг пулов обмена

javascript
function getBuyProfit(poolAddress, sDAI, sUSDe, amountIn, entryPriceForDAI) { var data = exchange.IO("api", poolAddress, "get_dy", sDAI["idx"], sUSDe["idx"], toInnerAmount(amountIn, sDAI["decimals"])) Log("get_dy:", data) var amountOut = toAmount(data, sUSDe["decimals"]) if (!amountOut) { return null } var profit = amountOut - entryPriceForDAI * amountIn return {"profit": profit, "amountOut": amountOut, "sDAI_sUSDe_price": amountOut / amountIn} }

Условия срабатывания триггера спроектированы следующим образом:

javascript
if (profit > 1000 && sDAI_Balance > amountIn) { Log("达到兑换条件,开始执行 sDAI -> sUSDe 兑换交易...") /* 兑换操作代码仅为教学演示,该功能请慎用,请先测试 executeTrade(poolAddress, sDAI, sUSDe, amountIn, 0.999*amountOut) */ }

Операция обмена может быть выполнена только в том случае, если текущая сумма обмена удовлетворяет прибыли более 1000 и в кошельке достаточно токенов sDAI.

Операция обмена

javascript
function executeTrade(poolAddress, tokenIn, tokenOut, amountIn, minOutAmount) { // exchange : i , j , _dx , _min_dy var swapTx = exchange.IO("api", poolAddress, "exchange", tokenIn["idx"], tokenOut["idx"], toInnerAmount(amountIn, tokenIn["decimals"]), toInnerAmount(minOutAmount, tokenOut["decimals"])) if (swapTx) { while (true) { Sleep(1000 * 3) let info = e.IO("api", "eth", "eth_getTransactionReceipt", swapTx) if (info && info.gasUsed) { return true } Log('Transaction not yet mined', swapTx) } } return false }

img

Полный код стратегии

javascript
function toAmount(s, decimals) { return Number((BigDecimal(BigInt(s)) / BigDecimal(Math.pow(10, decimals))).toString()) } function toInnerAmount(n, decimals) { return (BigDecimal(n) * BigDecimal(Math.pow(10, decimals))).toFixed(0) } function getBuyProfit(poolAddress, sDAI, sUSDe, amountIn, entryPriceForDAI) { var data = exchange.IO("api", poolAddress, "get_dy", sDAI["idx"], sUSDe["idx"], toInnerAmount(amountIn, sDAI["decimals"])) var amountOut = toAmount(data, sUSDe["decimals"]) if (!amountOut) { return null } var profit = amountOut - entryPriceForDAI * amountIn return {"profit": profit, "amountOut": amountOut, "sDAI_sUSDe_price": amountOut / amountIn} } function executeTrade(poolAddress, tokenIn, tokenOut, amountIn, minOutAmount) { // exchange : i , j , _dx , _min_dy var swapTx = exchange.IO("api", poolAddress, "exchange", tokenIn["idx"], tokenOut["idx"], toInnerAmount(amountIn, tokenIn["decimals"]), toInnerAmount(minOutAmount, tokenOut["decimals"])) if (swapTx) { while (true) { Sleep(1000 * 3) let info = e.IO("api", "eth", "eth_getTransactionReceipt", swapTx) if (info && info.gasUsed) { return true } Log('Transaction not yet mined', swapTx) } } return false } // 加密/解密方式 function cryptoKey(type, data, passWord, count) { // 加载加密库 eval(HttpQuery("https://cdnjs.cloudflare.com/ajax/libs/aes-js/3.1.2/index.min.js")) // sha256 密码 var hash = Encode("sha256", "string", "hex", passWord).substring(0, 32) if (type == "encrypt") { var key = aesjs.utils.utf8.toBytes(hash.substring(0, 32)) var counter = new aesjs.Counter(count) var textBytes = aesjs.utils.utf8.toBytes(data) var aesCtr = new aesjs.ModeOfOperation.ctr(key, counter) var encryptedBytes = aesCtr.encrypt(textBytes) var encryptedHex = aesjs.utils.hex.fromBytes(encryptedBytes) return encryptedHex } else if (type == "decrypt") { var key = aesjs.utils.utf8.toBytes(hash.substring(0, 32)) var counter = new aesjs.Counter(count) var aesCtrDecrypt = new aesjs.ModeOfOperation.ctr(key, counter) const decryptedBytes = aesCtrDecrypt.decrypt(aesjs.utils.hex.toBytes(data)) const decryptedText = aesjs.utils.utf8.fromBytes(decryptedBytes) return decryptedText } else { throw "function cryptoKey(), param 'type' not support" } } // 加密/解密选项 const descCryptoType = ["encrypt", "decrypt"] function main() { LogReset(1) var count = _G("count") if (!count) { count = new Date().getTime() _G("count", count) } var walletAddress = null if (cryptoType == 1) { exchange.IO("key", cryptoKey(descCryptoType[cryptoType], keyData, password, count)) walletAddress = exchange.IO("address") Log("载入秘钥,钱包地址:", walletAddress) } else { Log("加密后的秘钥:", cryptoKey(descCryptoType[cryptoType], keyData, password, count)) return } Log("钱包ETH余额:", toAmount(exchange.IO("api", "eth", "eth_getBalance", walletAddress, "latest"), 18)) // sDAI/sUSDe 池合约地址和ABI var poolAddress = "0x167478921b907422F8E88B43C4Af2B8BEa278d3A" // 合约ABI var poolABI = `[{"name":"Transfer","inputs":[{"name":"sender","type":"address","indexed":true},{"name":"receiver","type":"address","indexed":true},{"name":"value","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"Approval","inputs":[{"name":"owner","type":"address","indexed":true},{"name":"spender","type":"address","indexed":true},{"name":"value","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"TokenExchange","inputs":[{"name":"buyer","type":"address","indexed":true},{"name":"sold_id","type":"int128","indexed":false},{"name":"tokens_sold","type":"uint256","indexed":false},{"name":"bought_id","type":"int128","indexed":false},{"name":"tokens_bought","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"TokenExchangeUnderlying","inputs":[{"name":"buyer","type":"address","indexed":true},{"name":"sold_id","type":"int128","indexed":false},{"name":"tokens_sold","type":"uint256","indexed":false},{"name":"bought_id","type":"int128","indexed":false},{"name":"tokens_bought","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"AddLiquidity","inputs":[{"name":"provider","type":"address","indexed":true},{"name":"token_amounts","type":"uint256[]","indexed":false},{"name":"fees","type":"uint256[]","indexed":false},{"name":"invariant","type":"uint256","indexed":false},{"name":"token_supply","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"RemoveLiquidity","inputs":[{"name":"provider","type":"address","indexed":true},{"name":"token_amounts","type":"uint256[]","indexed":false},{"name":"fees","type":"uint256[]","indexed":false},{"name":"token_supply","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"RemoveLiquidityOne","inputs":[{"name":"provider","type":"address","indexed":true},{"name":"token_id","type":"int128","indexed":false},{"name":"token_amount","type":"uint256","indexed":false},{"name":"coin_amount","type":"uint256","indexed":false},{"name":"token_supply","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"RemoveLiquidityImbalance","inputs":[{"name":"provider","type":"address","indexed":true},{"name":"token_amounts","type":"uint256[]","indexed":false},{"name":"fees","type":"uint256[]","indexed":false},{"name":"invariant","type":"uint256","indexed":false},{"name":"token_supply","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"RampA","inputs":[{"name":"old_A","type":"uint256","indexed":false},{"name":"new_A","type":"uint256","indexed":false},{"name":"initial_time","type":"uint256","indexed":false},{"name":"future_time","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"StopRampA","inputs":[{"name":"A","type":"uint256","indexed":false},{"name":"t","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"ApplyNewFee","inputs":[{"name":"fee","type":"uint256","indexed":false},{"name":"offpeg_fee_multiplier","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"SetNewMATime","inputs":[{"name":"ma_exp_time","type":"uint256","indexed":false},{"name":"D_ma_time","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"stateMutability":"nonpayable","type":"constructor","inputs":[{"name":"_name","type":"string"},{"name":"_symbol","type":"string"},{"name":"_A","type":"uint256"},{"name":"_fee","type":"uint256"},{"name":"_offpeg_fee_multiplier","type":"uint256"},{"name":"_ma_exp_time","type":"uint256"},{"name":"_coins","type":"address[]"},{"name":"_rate_multipliers","type":"uint256[]"},{"name":"_asset_types","type":"uint8[]"},{"name":"_method_ids","type":"bytes4[]"},{"name":"_oracles","type":"address[]"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"exchange","inputs":[{"name":"i","type":"int128"},{"name":"j","type":"int128"},{"name":"_dx","type":"uint256"},{"name":"_min_dy","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"exchange","inputs":[{"name":"i","type":"int128"},{"name":"j","type":"int128"},{"name":"_dx","type":"uint256"},{"name":"_min_dy","type":"uint256"},{"name":"_receiver","type":"address"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"exchange_received","inputs":[{"name":"i","type":"int128"},{"name":"j","type":"int128"},{"name":"_dx","type":"uint256"},{"name":"_min_dy","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"exchange_received","inputs":[{"name":"i","type":"int128"},{"name":"j","type":"int128"},{"name":"_dx","type":"uint256"},{"name":"_min_dy","type":"uint256"},{"name":"_receiver","type":"address"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"add_liquidity","inputs":[{"name":"_amounts","type":"uint256[]"},{"name":"_min_mint_amount","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"add_liquidity","inputs":[{"name":"_amounts","type":"uint256[]"},{"name":"_min_mint_amount","type":"uint256"},{"name":"_receiver","type":"address"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"remove_liquidity_one_coin","inputs":[{"name":"_burn_amount","type":"uint256"},{"name":"i","type":"int128"},{"name":"_min_received","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"remove_liquidity_one_coin","inputs":[{"name":"_burn_amount","type":"uint256"},{"name":"i","type":"int128"},{"name":"_min_received","type":"uint256"},{"name":"_receiver","type":"address"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"remove_liquidity_imbalance","inputs":[{"name":"_amounts","type":"uint256[]"},{"name":"_max_burn_amount","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"remove_liquidity_imbalance","inputs":[{"name":"_amounts","type":"uint256[]"},{"name":"_max_burn_amount","type":"uint256"},{"name":"_receiver","type":"address"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"remove_liquidity","inputs":[{"name":"_burn_amount","type":"uint256"},{"name":"_min_amounts","type":"uint256[]"}],"outputs":[{"name":"","type":"uint256[]"}]},{"stateMutability":"nonpayable","type":"function","name":"remove_liquidity","inputs":[{"name":"_burn_amount","type":"uint256"},{"name":"_min_amounts","type":"uint256[]"},{"name":"_receiver","type":"address"}],"outputs":[{"name":"","type":"uint256[]"}]},{"stateMutability":"nonpayable","type":"function","name":"remove_liquidity","inputs":[{"name":"_burn_amount","type":"uint256"},{"name":"_min_amounts","type":"uint256[]"},{"name":"_receiver","type":"address"},{"name":"_claim_admin_fees","type":"bool"}],"outputs":[{"name":"","type":"uint256[]"}]},{"stateMutability":"nonpayable","type":"function","name":"withdraw_admin_fees","inputs":[],"outputs":[]},{"stateMutability":"view","type":"function","name":"last_price","inputs":[{"name":"i","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"ema_price","inputs":[{"name":"i","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"get_p","inputs":[{"name":"i","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"price_oracle","inputs":[{"name":"i","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"D_oracle","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"transfer","inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"outputs":[{"name":"","type":"bool"}]},{"stateMutability":"nonpayable","type":"function","name":"transferFrom","inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"outputs":[{"name":"","type":"bool"}]},{"stateMutability":"nonpayable","type":"function","name":"approve","inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"outputs":[{"name":"","type":"bool"}]},{"stateMutability":"nonpayable","type":"function","name":"permit","inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"},{"name":"_deadline","type":"uint256"},{"name":"_v","type":"uint8"},{"name":"_r","type":"bytes32"},{"name":"_s","type":"bytes32"}],"outputs":[{"name":"","type":"bool"}]},{"stateMutability":"view","type":"function","name":"DOMAIN_SEPARATOR","inputs":[],"outputs":[{"name":"","type":"bytes32"}]},{"stateMutability":"view","type":"function","name":"get_dx","inputs":[{"name":"i","type":"int128"},{"name":"j","type":"int128"},{"name":"dy","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"get_dy","inputs":[{"name":"i","type":"int128"},{"name":"j","type":"int128"},{"name":"dx","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"calc_withdraw_one_coin","inputs":[{"name":"_burn_amount","type":"uint256"},{"name":"i","type":"int128"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"totalSupply","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"get_virtual_price","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"calc_token_amount","inputs":[{"name":"_amounts","type":"uint256[]"},{"name":"_is_deposit","type":"bool"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"A","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"A_precise","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"balances","inputs":[{"name":"i","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"get_balances","inputs":[],"outputs":[{"name":"","type":"uint256[]"}]},{"stateMutability":"view","type":"function","name":"stored_rates","inputs":[],"outputs":[{"name":"","type":"uint256[]"}]},{"stateMutability":"view","type":"function","name":"dynamic_fee","inputs":[{"name":"i","type":"int128"},{"name":"j","type":"int128"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"ramp_A","inputs":[{"name":"_future_A","type":"uint256"},{"name":"_future_time","type":"uint256"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"stop_ramp_A","inputs":[],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"set_new_fee","inputs":[{"name":"_new_fee","type":"uint256"},{"name":"_new_offpeg_fee_multiplier","type":"uint256"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"set_ma_exp_time","inputs":[{"name":"_ma_exp_time","type":"uint256"},{"name":"_D_ma_time","type":"uint256"}],"outputs":[]},{"stateMutability":"view","type":"function","name":"N_COINS","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"coins","inputs":[{"name":"arg0","type":"uint256"}],"outputs":[{"name":"","type":"address"}]},{"stateMutability":"view","type":"function","name":"fee","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"offpeg_fee_multiplier","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"admin_fee","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"initial_A","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"future_A","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"initial_A_time","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"future_A_time","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"admin_balances","inputs":[{"name":"arg0","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"ma_exp_time","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"D_ma_time","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"ma_last_time","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"name","inputs":[],"outputs":[{"name":"","type":"string"}]},{"stateMutability":"view","type":"function","name":"symbol","inputs":[],"outputs":[{"name":"","type":"string"}]},{"stateMutability":"view","type":"function","name":"decimals","inputs":[],"outputs":[{"name":"","type":"uint8"}]},{"stateMutability":"view","type":"function","name":"version","inputs":[],"outputs":[{"name":"","type":"string"}]},{"stateMutability":"view","type":"function","name":"balanceOf","inputs":[{"name":"arg0","type":"address"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"allowance","inputs":[{"name":"arg0","type":"address"},{"name":"arg1","type":"address"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"nonces","inputs":[{"name":"arg0","type":"address"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"salt","inputs":[],"outputs":[{"name":"","type":"bytes32"}]}]` // 注册ABI exchange.IO("abi", poolAddress, poolABI) // 获取池子中的代币地址、名称 var token0Address = exchange.IO("api", poolAddress, "coins", 0) var token1Address = exchange.IO("api", poolAddress, "coins", 1) var token0Name = exchange.IO("api", token0Address, "symbol") var token1Name = exchange.IO("api", token1Address, "symbol") var token0Decimals = exchange.IO("api", token0Address, "decimals") var token1Decimals = exchange.IO("api", token1Address, "decimals") var sDAI = {} var sUSDe = {} if (token0Name == "sDAI") { sDAI["name"] = token0Name sDAI["address"] = token0Address sDAI["idx"] = 0 sDAI["decimals"] = token0Decimals ? token0Decimals : 18 } else { throw "pool error" } if (token1Name == "sUSDe") { sUSDe["name"] = token1Name sUSDe["address"] = token1Address sUSDe["idx"] = 1 sUSDe["decimals"] = token1Decimals ? token1Decimals : 18 } else { throw "pool error" } // 假设 DAI 入手成本价: 0.9929 var entryPriceForDAI = 0.9929 while (true) { var sDAI_Balance = exchange.IO("api", sDAI["address"], "balanceOf", walletAddress) var sUSDe_Balance = exchange.IO("api", sUSDe["address"], "balanceOf", walletAddress) if (!sDAI_Balance || !sUSDe_Balance) { Sleep(1000 * 5) continue } var tbl = {"type": "table", "title": "data", "cols": ["tokenName", "address", "idx", "decimals", "balance"], "rows": []} tbl["rows"].push([sDAI["name"], sDAI["address"], sDAI["idx"], sDAI["decimals"], toAmount(sDAI_Balance, sDAI["decimals"])]) tbl["rows"].push([sUSDe["name"], sUSDe["address"], sUSDe["idx"], sUSDe["decimals"], toAmount(sUSDe_Balance, sUSDe["decimals"])]) // 监控兑换价格,根据 DAI 入手成本价,计算实时利润等信息 var amountIn = 100000 var ret = getBuyProfit(poolAddress, sDAI, sUSDe, amountIn, entryPriceForDAI) if (!ret) { Sleep(1000 * 5) continue } var profit = ret["profit"] var amountOut = ret["amountOut"] var sDAI_sUSDe_price = ret["sDAI_sUSDe_price"] if (profit > 1000 && sDAI_Balance > amountIn) { Log("达到兑换条件,开始执行 sDAI -> sUSDe 兑换交易...") /* 兑换操作代码仅为教学演示,该功能请慎用,请先测试 executeTrade(poolAddress, sDAI, sUSDe, amountIn, 0.999*amountOut) */ } LogStatus(_D(), ", amountIn:", amountIn, ", amountOut:", amountOut, ", sDAI_sUSDe_price:", sDAI_sUSDe_price, ", profit:", profit, "\n`" + JSON.stringify(tbl) + "`") Sleep(1000 * 60) } }

END

Согласно идее разработки оригинальной стратегии, целью должно было стать улавливание экстремальных рыночных условий, подобных показанным на рисунке.

img

Спасибо за ваше чтение и поддержку.

Comment
All comments (0)
No data
No data
  • 1
iPhone Download
Forums
PINE Language
© 2015 - ∞ INVENTOR PTE LTD (SG)