Создание транзакции
В данной статье мы будем использоваться этот кошелек для примера:
Address: 0x026A25EfbcEFb2e481d005E4F00Ccced0AF511FF
Private Key: 0x1c1a49fea9a4ede1dc8e582639f498d41fa3c4a9e2ab2b9d740a4a3ec14e1cbf
Уровень-1 (Layer-1)
Единственная транзакция, которая совершается на Уровне-1 – это депозит. Она имеет два подтипа DepositETH и DepositERC20
.
ABIs
[
{
"constant": false,
"inputs": [
{
"internalType": "contract IERC20",
"name": "_token",
"type": "address"
},
{
"internalType": "uint104",
"name": "_amount",
"type": "uint104"
},
{
"internalType": "address",
"name": "_franklinAddr",
"type": "address"
}
],
"name": "depositERC20",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"internalType": "address",
"name": "_franklinAddr",
"type": "address"
}
],
"name": "depositETH",
"outputs": [],
"payable": true,
"stateMutability": "payable",
"type": "function"
}
]
Депозит ETH
Пример кода:
import { Wallet, Contract, utils } from 'ethers'
const contract = new Contract('0x8ECa806Aecc86CE90Da803b080Ca4E3A9b8097ad', ABI, wallet)
const wallet = new Wallet('0x1c1a49fea9a4ede1dc8e582639f498d41fa3c4a9e2ab2b9d740a4a3ec14e1cbf')
async function depositETH(amount) {
const tx = await contract.depositETH(wallet.address, {
value: utils.parse(amount)
})
return tx
}
// deposit 1 ETH
depositETH('1').then(console.log)
Депозит ERC20
Как и в других проектах вы должны подтвердить основной адрес контракта ZKSwap, чтобы внести свои токенты ERC20 на депозит. Будьте осторожны с токенами, у которых есть ограничения (Подробнее см. здесь).
Пример кода:
import { Wallet, Contract, utils } from 'ethers'
const contract = new Contract('0x8ECa806Aecc86CE90Da803b080Ca4E3A9b8097ad', ABI, wallet)
const wallet = new Wallet('0x1c1a49fea9a4ede1dc8e582639f498d41fa3c4a9e2ab2b9d740a4a3ec14e1cbf')
async function depositERC20(amount, tokenAddress) {
const tokenContract = new Contract(tokenAddress, ERC20_ABI, wallet)
// check allowance
const allowance = await tokenContract.allowance(wallet.address, MAIN_CONTRACT_ADDRESS)
let nonce
if (allowance.lt(utils.parse(amount)) {
// approve
const MAX_AMOUNT = '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
const approveTx = await tokenContract.allow(MAIN_CONTRACT_ADDRESS, MAX_AMOUNT)
nonce = approveTx.nonce + 1
}
const tx = await contract.depositERC20(tokenAddress, utils.parse(amount), wallet.address, {
nonce
})
return tx
}
// deposit 100 ZKS
depositERC20('100', '0xe4815ae53b124e7263f08dcdbbb757d41ed658c6').then(console.log)
Уровень-2
При отправке транзакции на ZKSwap через API необходимо заполнить три поля: tx
, signature
и fastProcessing
. Далее по тексту Signed Transaction
относиться к полю tx
, а ETH Signature относится к полю signature
.
Приватный ключ
Подпишите следующее сообщение приватным ключом Уровня 1, чтобы получить сид фразу Уровня 2. И используйте криптографические библиотеки zkSync, чтобы получить приватный ключ.
Access ZKSwap account.
Only sign this message for a trusted client!
Вот полный пример получения приватного ключа с помощью zksync-crypto в JavaScript.
import { Wallet, Contract, utils } from 'ethers'
import { privateKeyFromSeed, private_key_to_pubkey_hash } from 'zksync-crypto'
const wallet = new Wallet('0x1c1a49fea9a4ede1dc8e582639f498d41fa3c4a9e2ab2b9d740a4a3ec14e1cbf')
async function getPrivateKey() {
const msg = 'Access ZKSwap account.\n\nOnly sign this message for a trusted client!'
const signature = await wallet.signMessage(msg)
const seed = utils.arrayify(signature)
// Get private key
const privateKey = privateKeyFromSeed(seed)
return privateKey
}
getPrivateKey().then(console.log)
Хеш открытого ключа
После получения приватного ключа вам необходимо зарегистрировать хэш открытого ключа в ZKSwap, чтобы он мог верифицировать отправленные вами транзакции.
import { utils } from 'ethers'
import { private_key_to_pubkey_hash } from 'zksync-crypto'
const pubKeyHash = `sync:${utils.hexlify(private_key_to_pubkey_hash(privateKey)).substr(2)}`
Подпись
Перед отправкой транзакции в ZKSwap вам необходимо подписать данные транзакции.
import { utils } from 'ethers'
import { sign_musig } from 'zksync-crypto'
function signMessage(privateKey, msgBytes) {
const signaturePacked = sign_musig(privateKey, msgBytes)
const pubKey = utils.hexlify(signaturePacked.slice(0, 32)).substr(2)
const signature = utils.hexlify(signaturePacked.slice(32)).substr(2)
return {
pubKey,
signature
}
}
const msgBytes = utils.concat([type, accountId, ...etc])
const signature = signMessage(privateKey, msgBytes)
Замена открытого ключа
После того, как учетная запись была «зарегистрирована» в ZKSwap (посредством перевода или депозита), вы можете изменить pubKeyHash учетной записи, чтобы совершать любую транзакцию на Уровне 2. Это особая транзакция, которую не нужно подписывать приватным ключом Уровня 2.
Поля транзакции
Field
Type
Comment
type
string
ChangePubKey
accountId
number
Your account ID.
account
address
Your address.
newPkHash
number
The public key hash.
nonce
number
Your current nonce.
ethSignature
string
Layer-1 signature
Пример подписанной транзакции
{
"type": "ChangePubKey",
"accountId": 83670,
"account": "0x026A25EfbcEFb2e481d005E4F00Ccced0AF511FF",
"newPkHash": "sync:83f62ba777515089eb905a375f77f59ddfada116",
"nonce": 0,
"ethSignature": "0x66c1ef3611a634e400301375b291a0835b0e31237273e1bdab45acc3ef27c761674fd5e5a706566e5175e8e18306f5b8d1d36016f3894e84d527c3c97e92bcf71c"
}
ETH подпись
Register ZKSwap pubkey:
{pubKeyHash}
nonce: {hexlifiedNonce}
account id: {hexlifiedAccountId}
Only sign this message for a trusted client!
Перевод
Поля транзакции
Bytes Order
Field
Type
Bytes Length
Comment
Bytes Example
0
type
string
1
Transfer
0x05
1
accountId
number
4
Your account ID.
0x0000053a
2
from
address
20
Your address.
0x026a25efbcefb2e481d005e4f00ccced0af511ff
3
to
address
20
The target address you want to transfer.
0x961b513dfd3e363c238e0f98219ee02552a847bd
4
token
number
2
The ID of the token.
0x000a
5
amount
string
5
The amount you want to transfer.
0x4a817c8008
6
feeToken
number
1
The ID of fee token.
0x0a
7
fee
string
2
0x0000
8
chainId
number
1
11 for mainnet, 128 for ropsten.
0x0b
9
nonce
number
4
Your current nonce.
0x00000001
-
signature
object
Contains your pubKey
and signature.
Пример Full Bytes
0x050000053a026a25efbcefb2e481d005e4f00ccced0af511ff961b513dfd3e363c238e0f98219ee02552a847bd000a4a817c80080a00000b00000001
Пример подписанной транзакции
{
"type": "Transfer",
"accountId": 1338,
"from": "0x026A25EfbcEFb2e481d005E4F00Ccced0AF511FF",
"to": "0x961b513dfd3e363c238e0f98219ee02552a847bd",
"token": 10,
"amount": "1000000000000000000",
"feeToken": 10,
"fee": "0",
"chainId": 11,
"nonce": 1,
"signature": {
"pubKey": "110ffd569daaee30068fc3c85922d1237f63a41d4749d464b883131e92369204",
"signature": "7db4f4ce33abf89cbccaff96ae0651c79043dcf965893de71e7388163ec57883b2d4ef9bf264346ceff69f9ba8dfe8624d1fad9a452acf10a5d15f956a0a7b03"
}
}
ETH подпись
Transfer {readableAmount} {tokenSymbol}
To: {to}
ChainId {chainId}
Nonce: {nonce}
Fee: {readableFee} {feeTokenSymbol}
Account Id: {accountId}
Вывод
Поля транзакции
Bytes Order
Field
Type
Bytes Length
Comment
Bytes Example
0
type
string
1
Withdraw
0x03
1
accountId
number
4
Your account ID.
0x0000053a
2
from
address
20
Your address.
0x026a25efbcefb2e481d005e4f00ccced0af511ff
3
to
address
20
The target address you want to withdraw to.
0x026a25efbcefb2e481d005e4f00ccced0af511ff
4
token
number
2
The ID of the token you want to withdraw.
0x000a
5
amount
string
16
The amount you want to withdraw.
0x00000000000000000de0b6b3a7640000
6
feeToken
number
1
The ID of fee token.
0x0a
7
fee
string
2
0x4bf0
8
chainId
number
1
11 for mainnet, 128 for ropsten.
0x0b
9
nonce
number
4
Your current nonce.
0x00000002
-
signature
object
Contains your pubKey
and signature.
Пример Full Bytes
0x030000053a026a25efbcefb2e481d005e4f00ccced0af511ff026a25efbcefb2e481d005e4f00ccced0af511ff000a00000000000000000de0b6b3a76400000a4bf00b00000002
Пример подписанной транзакции
{
"type": "Withdraw",
"accountId": 1338,
"from": "0x026A25EfbcEFb2e481d005E4F00Ccced0AF511FF",
"to": "0x026a25efbcefb2e481d005e4f00ccced0af511ff",
"token": 10,
"amount": "1000000000000000000",
"feeToken": 10,
"fee": "6070000000000000000",
"chainId": 11,
"nonce": 2,
"signature": {
"pubKey": "110ffd569daaee30068fc3c85922d1237f63a41d4749d464b883131e92369204",
"signature": "68bb8413edc0182812aa90481ff46f0514df9d5d6b5703338f1a292682caad9b04cac623f95b9d26fa31d4a9330ba35b5746fd697853a0512f92b00692fe6d00"
}
}
ETH подпись
Withdraw {readableAmount} {tokenSymbol}
To: {to}
ChainId {chainId}
Nonce: {nonce}
Fee: {readableFee} {feeTokenSymbol}
Account Id: {accountId}
Обмен
Комиссия
Для примера обменяем токен А на токен В. Есть два способа:
Если А – это токен комиссии, то ее размер рассчитывается как
amountIn * 5 / 9995
Если А не выступает в роли токена комиссии, а для комиссии применяется токен В, то ее размер
amountOut * 5 /10000
. Это неamountOutMin
.amountOut
равенamountOutMin
и тогда проскальзывание равно 0.
Поля транзакции
Bytes Order
Field
Type
Bytes Length
Comment
Bytes Example
0
type
string
1
Swap
0x0b
1
accountId
number
4
Your account ID.
0x0000053a
2
from
address
20
Your address.
0x026a25efbcefb2e481d005e4f00ccced0af511ff
3
to
address
20
The pair's address.
0xaa45c964e21eafb38574e9d000adbaf85acfbb80
4
tokenIn
number
2
The ID of the token you want to swap in.
0x000a
5
amountIn
string
5
The amount you want to swap in.
0x94efe63009
6
tokenOut
number
2
The ID of the token you want to swap out.
0x0000
7
amountOutMin
string
5
The minimum amount you want to swap out.
0x25004d47c6
8
feeToken
number
1
The ID of fee token.
0x0a
9
fee
string
2
0x7d0d
10
chainId
number
1
11 for mainnet, 128 for ropsten.
0x0b
11
nonce
number
4
Your current nonce.
0x00000003
-
signature
object
Contains your pubKey
and signature.
Пример Full Bytes
0x0b0000053a026a25efbcefb2e481d005e4f00ccced0af511ffaa45c964e21eafb38574e9d000adbaf85acfbb80000a94efe63009000025004d47c60a7d0d0b00000003
Пример подписанной транзакции
{
"type": "Swap",
"accountId": 1338,
"from": "0x026A25EfbcEFb2e481d005E4F00Ccced0AF511FF",
"to": "0xaa45c964e21eafb38574e9d000adbaf85acfbb80",
"tokenIn": 10,
"tokenOut": 0,
"amountIn": "19990000000000000000",
"amountOutMin": "4966214206000000",
"feeToken": 10,
"fee": "10000000000000000",
"chainId": 11,
"nonce": 3,
"signature": {
"pubKey": "110ffd569daaee30068fc3c85922d1237f63a41d4749d464b883131e92369204",
"signature": "3c6c2059ab0e929ed18d6ad4fbbf1cddce0e84b0cb9537069456b16cd01f33a2bc5391f8f7e1b9ae8fdff4c5d05856709e6bfd0e9200f5293386cf1aa6b39c00"
}
}
ETH подпись
Swap {readableAmontIn} {tokenInSymbol}
Minimum: {readableAmontOutMin} {tokenOutSymbol}
To: {pairAddress}
ChainId {chainId}
Nonce: {nonce}
Fee: {readableFee} {feeTokenSymbol}
Account Id: {accountId}
Добавление ликвидности
Поля транзакции
Bytes Order
Field
Type
Bytes Length
Comment
Bytes Example
0
type
string
1
AddLiquidity
0x09
1
accountId
number
4
Your account ID.
0x0000053a
2
from
address
20
Your address.
0x026a25efbcefb2e481d005e4f00ccced0af511ff
3
to
address
20
The pair's address.
0xaa45c964e21eafb38574e9d000adbaf85acfbb80
4
tokenA
number
2
The ID of token A.
0x0000
5
amountADesired
number
5
The amount of token A you want to add to the pair.
0xc2cf6f3245
6
amountAMin
string
5
The minimum amount of Token A you want to add to the pair.
0xb911dcd625
7
tokenB
number
2
The ID of the token B.
0x000a
8
amountBDesired
string
5
The amount of token B you want to add to the pair.
0x4a817c8009
9
amountBMin
string
5
The minimum amount of Token B you want to add to the pair.
0x46c7cfe009
10
tokenLiquidity
number
2
The pair ID.
0x4002
11
feeToken
number
1
The ID of fee token.
0x0a
12
fee
string
2
0x0000
13
chainId
number
1
11 for mainnet, 128 for ropsten.
0x0b
14
nonce
number
4
Your current nonce.
0x00000004
-
signature
object
Contains your pubKey
and signature.
Пример Full Bytes
0x090000053a026a25efbcefb2e481d005e4f00ccced0af511ffaa45c964e21eafb38574e9d000adbaf85acfbb800000c2cf6f3245b911dcd625000a4a817c800946c7cfe00940020a00000b00000004
Пример подписанной транзакции
{
"type": "AddLiquidity",
"accountId": 1338,
"from": "0x026A25EfbcEFb2e481d005E4F00Ccced0AF511FF",
"to": "0xaa45c964e21eafb38574e9d000adbaf85acfbb80",
"tokenA": 0,
"tokenB": 10,
"tokenLiquidity": 16386,
"amountADesired": "2614699457800000",
"amountBDesired": "10000000000000000000",
"amountAMin": "2483964484900000",
"amountBMin": "9500000000000000000",
"feeToken": 10,
"fee": "0",
"chainId": 11,
"nonce": 4,
"signature": {
"pubKey": "110ffd569daaee30068fc3c85922d1237f63a41d4749d464b883131e92369204",
"signature": "3506a865b8a0871b706a620abbf7978760f76670c2d563f059d217890349988dd7a37d1cea3f67d5ca691453dd45d282141acac3f4dafb9f7a44b1dda3e0ca00"
}
}
ETH подпись
AddLiquidity {pairSymbol}
Desired: {readableAmontA} {tokenASymbol} {readableAmontB} {tokenBSymbol}
Minimum: {readableAmontAMin} {tokenASymbol} {readableAmontBMin} {tokenBSymbol}
To: {pairAddress}
ChainId {chainId}
Nonce: {nonce}
Fee: {readableFee} {feeTokenSymbol}
Account Id: {accountId}
Удаление ликвидности
Поля транзакции
Bytes Order
Field
Type
Comment
Bytes Examplle
0
type
string
1
RemoveLiquidity
0x0a
1
accountId
number
4
Your account ID.
0x0000053a
2
from
address
20
Your address.
0x026a25efbcefb2e481d005e4f00ccced0af511ff
3
to
address
20
The pair's address.
0xaa45c964e21eafb38574e9d000adbaf85acfbb80
4
tokenA
number
2
The ID of token A.
0x0000
5
amountAMin
string
5
The minimum amount of Token A you want to remove from the pair.
0xb96855c485
6
tokenB
number
2
The ID of the token B.
0x000a
7
amountBMin
string
5
The minimum amount of Token B you want to remove from the pair.
0x46a6e21049
8
feeToken
number
1
The ID of fee token.
0x0a
9
fee
string
2
0x0000
10
tokenLiquidity
number
2
The pair ID.
0x4002
11
amountLiquidity
string
5
The amount of LP token you want to remove.
0x77e80cdba7
12
chainId
number
2
11 for mainnet, 128 for ropsten.
0x0b
13
nonce
number
4
Your current nonce.
-
signature
object
Contains your pubKey
and signature.
Пример Full Bytes
0x0a0000053a026a25efbcefb2e481d005e4f00ccced0af511ffaa45c964e21eafb38574e9d000adbaf85acfbb800000b96855c485000a46a6e210490a0000400277e80cdba70b00000005
Пример подписанной транзакции
{
"type": "RemoveLiquidity",
"accountId": 1338,
"from": "0x026A25EfbcEFb2e481d005E4F00Ccced0AF511FF",
"to": "0xaa45c964e21eafb38574e9d000adbaf85acfbb80",
"tokenA": 0,
"tokenB": 10,
"amountAMin": "2488498128400000",
"amountBMin": "9482735746000000000",
"tokenLiquidity": 16386,
"amountLiquidity": "160935707810000000",
"feeToken": 10,
"fee": "0",
"chainId": 11,
"nonce": 5,
"signature": {
"pubKey": "110ffd569daaee30068fc3c85922d1237f63a41d4749d464b883131e92369204",
"signature": "bf0e5c3639e9f9f837e2d141fa9481da8e11574001dbe8cd81cb3005c9cac69ae05655d416cd53bedd27142235ad5743e9f26b66ac8643d859d0c8caf149a700"
}
}
ETH подпись
RemoveLiquidity {readableLiquidityAmount} {pairSymbol}
Minimum: {readableAmontAMin} {tokenASymbol} {readableAmontBMin} {tokenBSymbol}
To: {pairAddress}
ChainId {chainId}
Nonce: {nonce}
Fee: {readableFee} {feeTokenSymbol}
Account Id: {accountId}
Last updated
Was this helpful?