如何通過 0x.js SDK 集成 0x 協議

什麼是0x協議,它的工作機制是怎樣的?這個本文將介紹 0x協議 ,包括它的鏈下訂單中繼(撮合)、去中心化交易中繼器, 以及如何在以太坊公鏈或私鏈上通過0x智能合約構建自己的去中心化交易所(DEX)。

什麼是0x協議

0x是一種開放、以太坊上支持點對點資產交換的協議,其開源基礎架構使開發人員和企業能夠構建自己的交易所來交易所有ERC-20和ERC-721資產。

0x協議特性

0x協議有以下特性

  • 安全的非託管交易

    無需存款或取款,就可以直接實現錢包對錢包的資產交易。

  • 靈活的訂單類型

    可以選擇以當前價格賣出資產,或允許潛在買家出價。

  • 構建業務

    通過在每次交易中收取費用,可以使產品貨幣化,還可加入0x生態系統中越來越豐富的中繼器。

上面的0x協議特性可實現我們的去中心化兌換。

0x協議優勢

0x協議使用模塊化方式交易以太坊區塊鏈上資產,優勢有:

  • 可靠的智能合約

    0x協議的智能合約通過了兩輪嚴格的安全審覈。

  • 可擴展架構

    0x的模塊化管道支持開發者通過擴展API嵌入自己的智能合約。

  • 高效設計

    0x協議的鏈下訂單撮合、鏈上結算,是一種節省手續費的兌換方式。

0x協議可用於很多場景,例如遊戲、收藏品、預測市場、去中心化交易的訂單簿、 去中心化貸款等等。

其次,0x的智能合約,是模塊化的,可以通過治理進行升級, 而不會影響系統的其他組件,也不會引起市場的中斷。

0x協議的智能合約

0x協議的智能合約包含有:

  • Exchange Contract :資產兌換合約
  • ERC20 Proxy contract : ERC20代理合約
  • ERC721 Proxy contract :ERC721代理合約

資產兌換合約

包含0x協議的業務邏輯,是以下功能的入口:

  1. 提供訂單
  2. 訂單取消
  3. 執行交易
  4. 簽名驗證
  5. 在系統中註冊新資產

ERC20代理合約

該合約代表用戶要轉讓ERC20代幣。 因此,每個用戶(ERC20代幣持有者)都必須授權(approve)該合約可以操作自己持有的ERC20代幣。

ERC721 代理合約

該合約代表用戶要轉讓ERC721代幣。 因此,每個用戶(ERC721代幣持有者)都必須授權(approve)該合約可以操作自己持有的ERC721代幣。

爲了部署及使用0x協議智能合約,需要先安裝0x.js。0x.js是一個與0x協議交互的 JavaScript庫,利用它就可以輕鬆地調用0x協議的智能合約來創建、取消或驗證訂單,以及檢查 ERC20和ERC721代幣持有者的授權額度和餘額。

深入0x 合約架構

0x協議採用鏈下訂單撮合、鏈上結算的模式,密碼學簽名的訂單可以在鏈下通過任意渠道通信。 感興趣的對手方可以將這些訂單中的一個或多個注入到0x的資產兌換合約中,進行鏈上交易結算。

0x協議可以交換任何ERC20或ERC721資產。上圖顯示了當Taker(喫單者)向0x資產兌換合約(Exchange)提交訂單時資產轉移的實際處理流程(以下需要對應的上圖的標號):

注:兌換交易中,Maker(掛單者)和Taker(喫單者)。掛單是提供流動性,其訂單是被動成交的。喫單剛好相反,是利用流動性主動交易。

  1. Taker(喫單者)調用資產兌換合約的 fillOrder() 方法提交簽名訂單。
  2. 資產兌換合約將訂單傳遞給相應的ERC20代理合約,實際的代幣轉賬是在代理合約上進行的。 注意 :Maker和Taker必須先授權ERC20代理合約,然後再提交訂單。
  3. 在ERC20代理合約中調用(掛單者)ERC20代幣合約的 transferFrom() 方法
  4. 如果掛單者的ERC20合約調用失敗,則整個交易回滾。
  5. 交易從代理返回到兌換合約。
  6. 資產兌換合約將訂單傳遞到ERC20代理合同。
  7. 在資產代理合約中調用(喫單者)ERC20合約的 transferFrom() 方法
  8. 如果喫單者的ERC20合約調用失敗,則整個交易回滾。
  9. 交易從代理返回到兌換合約。
  10. 返回交易執行結果

接下來,我們將討論使用0x.js庫在以太坊上的部署0x智能合約,以便交易資產,使用 npm 安裝0x.js:

npm install 0x.js

部署0x智能合約

要與智能合約進行交互,我們需要部署0x智能合約,然後通過 0x.js庫用合約地址與合約進行交互。

資產兌換合約

資產兌換合約的源代碼在 此github ,資產兌換合約構造函數沒有參數,部署的時候不需要提供參數,部署者(msg.sender)將是合約的所有者(Owner)。所有者能夠在兌換合約中設置代理合約的地址。

ERC20代理合約

使用ERC20代理合約的 源代碼 進行部署,代理合約的構造函數不需要參數,部署者(msg.sender)將是合約的所有者。所有者將能夠在ERC20代理合約中設置資產兌換合約的地址。

ERC721代理合約

使用 ERC721代理合約 源代碼 進行部署,代理合約的構造函數不需要參數,部署者(msg.sender)將是合約的所有者。所有者將能夠在ERC721代理合約中設置資產兌換合約的地址。

與 0x 協議交互

與0x交互的最終目標是掛單者使用0x.js庫創建訂單,喫單者使用fillOrder()函數提交訂單進行兌換。

註冊合約

部署完以上合約後,需要在資產代理合約中設置兌換合約的地址,在兌換合約中設置資產代理合約的地址。

  • 調用資產兌換合約的 registerAssetProxy(ERC20 或 ERC71 代理合約地址) 方法將記錄資產代理合約的地址,兌換代幣交易是在代理合約中進行的。該方法只能由資產交換智能合約的所有者調用。

  • 調用ERC20代理合約的 addAuthorizedAddress(兌換合約) 方法註冊兌換合約。

  • 調用ERC20代理合約的 removeAuthorizedAddress(兌換地址) 方法刪除兌換合約。

合約配置

使用資產兌換合約和資產代理合約地址通過0x.js庫 進行交互 :

let contractConfig = {
  contractAddresses: {
    erc20Proxy: proxyAddress.toLowerCase(),
    erc721Proxy: "0x1d7022f5b17d2f8b695918fb48fa1089c9f85401",
    exchange: exchangeAddress.toLowerCase() 
  },
  networkId: networkId
};
  
const contractWrappers = new ContractWrappers(holderEngine, contractConfig);

現在就可以與部署在專用或測試網絡上的0x協議智能合約進行交互。 請記住添加RPC節點提供者以便與區塊鏈進行交互。

實例化

爲了與0x.js庫進行交互,我們需要導入(import)如下所示相關的軟件包

const {
  assetDataUtils,BigNumber,ContractWrappers,
  generatePseudoRandomSalt,orderHashUtils,signatureUtils
} = require('0x.js');

const TX_DEFAULTS = { gas: 400000 };
const { RPCSubprovider, Web3ProviderEngine } = require('0x.js');

let newWallet = new ethers.Wallet(wallet.signingKey.privateKey, prov);
const holderWallet = new PrivateKeyWalletSubprovider(wallet.signingKey.privateKey.slice(2));

添加RPC訂閱節點提供者:

const holderEngine = new Web3ProviderEngine();
holderEngine.addProvider(holderWallet);
// 訂閱節點提供者可以使用自定義URL分別連接以太坊主網、測試網或私鏈。
holderEngine.addProvider(new RPCSubprovider(providerUrl));
holderEngine.start();

獲取0x合約地址並實例化合約包裝器:

const contractWrappers = new ContractWrappers(holderEngine, contractConfig);
const web3Wrapper = new Web3Wrapper(providerEngine);
const contractAddresses = getContractAddressesForNetworkOrThrow(100);//networkID

ERC20合約授權

在掛單者(持有 tokenA)可以創建一個訂單並且喫單者(持有 token B)將提交訂單進行兌換之前,需要新進行授權。

先獲取相關合約地址:

// 合約地址
const tokenAAddress = contractAddresses.tokenA;
const tokenBAddress = contractAddresses.tokenB;
const exchange = contractAddresses.exchange;

所有地址都可以從0x.js庫獲取到。

// 將有關資產的所有必要信息編碼爲十六進制字符串

const makerAssetData = assetDataUtils.encodeERC20AssetData(tokenAAddress);
const takerAssetData = assetDataUtils.encodeERC20AssetData(tokenBAddress);
const makerAssetAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(100), DECIMALS);
const takerAssetAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(200), DECIMALS);
const NULL_ADDRESS = '0x0000000000000000000000000000000000000000';
const ZERO = new BigNumber(0);
const DECIMALS = 18;

現在掛單者和喫單者應該授權相應的資產代理合約,以便代理合約可以分別代表掛單者和喫單者轉移代幣:

// 授權
const makerApprovalTxHash = await contractWrappers.erc20Token.setUnlimitedProxyAllowanceAsync(
    tokenAAddress,
    maker,
);
await web3Wrapper.awaitTransactionSuccessAsync(makerApprovalTxHash);

// 授權
const takerApprovalTxHash = await contractWrappers.erc20Token.setUnlimitedProxyAllowanceAsync(
    tokenBAddress,
    taker,
);
await web3Wrapper.awaitTransactionSuccessAsync(takerApprovalTxHash);

在掛單者和喫單者授權資產代理合約之後,代理合約就可以分別代表掛單者和喫單者轉移代幣了。

接下來,掛單者將創建一個委託訂單並在鏈下簽名,而喫單者將在鏈上執行訂單。

創建訂單、驗證與喫單

創建訂單:

const order = {
  exchangeAddress: exchangeAddress,
  makerAddress: maker,//address of maker
  takerAddress: taker,//address of taker
  senderAddress: taker,// address of sender
  feeRecipientAddress: NULL_ADDRESS,//fee in the form of native currency of platform
  expirationTimeSeconds: randomExpiration,//訂單過期時間
  salt: generatePseudoRandomSalt(),// 隨機數,用來區分訂單
  makerAssetAmount,// 掛單資產數量
  takerAssetAmount,// taker asset amount
  makerAssetData,//encoded address of tokenA
  takerAssetData,//encoded address of tokenB
  makerFee: ZERO,//fee if required
  takerFee: ZERO,//fee if required
};

現在我們創建了一個資產交換委託訂單。接下來在調用0x.js庫的 getOrderHash() 函數獲得訂單哈希值以便進行簽名。這個哈希根據EIP712對訂單計算出來的:

const orderHashHex = orderHashUtils.getOrderHashHex(order);

獲取訂單的哈希後,掛單者使用0x.js庫的 ecSignHashAsync() 方法對訂單簽名。

const signature = await signatureUtils.ecSignHashAsync(providerEngine, orderHashHex, maker);
const signedOrder = { …order, signature };

喫單者可以使用資產交易合約的validateFillOrderThrowIfInvalidAsync`方法驗證訂單是否可以執行:

await contractWrappers.exchange.validateFillOrderThrowIfInvalidAsync(
  signedOrder, 
  takerAssetAmount, 
  taker
);

最終,喫單者調用資產交易合約的 fillOrderAsync 方法執行訂單:

try{
  txHash = await contractWrappers.exchange.fillOrderAsync(
    signedOrder, 
    takerAssetAmount, 
    taker, 
    {TX_DEFAULTS,}
  );
  
  var transaction = await web3Wrapper.awaitTransactionSuccessAsync(txHash);
}
catch(error){}

讓我們快速回顧一下到目前爲止所學到的知識,然後通過介紹已經建立在0x上的項目來結束我們的討論。

回顧

本文介紹了什麼是0x協議,其特點是什麼、它是如何工作的,以及如何掛單及喫單。

下面列出了已經使用0x協議實現DEX和訂單簿的項目。

DEX有: Radar Relay , paradex , Star bitex , LedgerDex

訂單簿有: open relay

原文鏈接: How to integrate 0x(ZRX) Protocol to setup your own Decentralized Exchange (DEX)

什麼是0x協議,它的工作機制是怎樣的?這個本文將介紹 0x協議 ,包括它的鏈下訂單中繼(撮合)、去中心化交易中繼器, 以及如何在以太坊公鏈或私鏈上通過0x智能合約構建自己的去中心化交易所(DEX)。

什麼是0x協議

0x是一種開放、以太坊上支持點對點資產交換的協議,其開源基礎架構使開發人員和企業能夠構建自己的交易所來交易所有ERC-20和ERC-721資產。

0x協議特性

0x協議有以下特性

  • 安全的非託管交易

    無需存款或取款,就可以直接實現錢包對錢包的資產交易。

  • 靈活的訂單類型

    可以選擇以當前價格賣出資產,或允許潛在買家出價。

  • 構建業務

    通過在每次交易中收取費用,可以使產品貨幣化,還可加入0x生態系統中越來越豐富的中繼器。

上面的0x協議特性可實現我們的去中心化兌換。

0x協議優勢

0x協議使用模塊化方式交易以太坊區塊鏈上資產,優勢有:

  • 可靠的智能合約

    0x協議的智能合約通過了兩輪嚴格的安全審覈。

  • 可擴展架構

    0x的模塊化管道支持開發者通過擴展API嵌入自己的智能合約。

  • 高效設計

    0x協議的鏈下訂單撮合、鏈上結算,是一種節省手續費的兌換方式。

0x協議可用於很多場景,例如遊戲、收藏品、預測市場、去中心化交易的訂單簿、 去中心化貸款等等。

其次,0x的智能合約,是模塊化的,可以通過治理進行升級, 而不會影響系統的其他組件,也不會引起市場的中斷。

0x協議的智能合約

0x協議的智能合約包含有:

  • Exchange Contract :資產兌換合約
  • ERC20 Proxy contract : ERC20代理合約
  • ERC721 Proxy contract :ERC721代理合約

資產兌換合約

包含0x協議的業務邏輯,是以下功能的入口:

  1. 提供訂單
  2. 訂單取消
  3. 執行交易
  4. 簽名驗證
  5. 在系統中註冊新資產

ERC20代理合約

該合約代表用戶要轉讓ERC20代幣。 因此,每個用戶(ERC20代幣持有者)都必須授權(approve)該合約可以操作自己持有的ERC20代幣。

ERC721 代理合約

該合約代表用戶要轉讓ERC721代幣。 因此,每個用戶(ERC721代幣持有者)都必須授權(approve)該合約可以操作自己持有的ERC721代幣。

爲了部署及使用0x協議智能合約,需要先安裝0x.js。0x.js是一個與0x協議交互的 JavaScript庫,利用它就可以輕鬆地調用0x協議的智能合約來創建、取消或驗證訂單,以及檢查 ERC20和ERC721代幣持有者的授權額度和餘額。

深入0x 合約架構

0x協議採用鏈下訂單撮合、鏈上結算的模式,密碼學簽名的訂單可以在鏈下通過任意渠道通信。 感興趣的對手方可以將這些訂單中的一個或多個注入到0x的資產兌換合約中,進行鏈上交易結算。

0x協議可以交換任何ERC20或ERC721資產。上圖顯示了當Taker(喫單者)向0x資產兌換合約(Exchange)提交訂單時資產轉移的實際處理流程(以下需要對應的上圖的標號):

注:兌換交易中,Maker(掛單者)和Taker(喫單者)。掛單是提供流動性,其訂單是被動成交的。喫單剛好相反,是利用流動性主動交易。

  1. Taker(喫單者)調用資產兌換合約的 fillOrder() 方法提交簽名訂單。
  2. 資產兌換合約將訂單傳遞給相應的ERC20代理合約,實際的代幣轉賬是在代理合約上進行的。 注意 :Maker和Taker必須先授權ERC20代理合約,然後再提交訂單。
  3. 在ERC20代理合約中調用(掛單者)ERC20代幣合約的 transferFrom() 方法
  4. 如果掛單者的ERC20合約調用失敗,則整個交易回滾。
  5. 交易從代理返回到兌換合約。
  6. 資產兌換合約將訂單傳遞到ERC20代理合同。
  7. 在資產代理合約中調用(喫單者)ERC20合約的 transferFrom() 方法
  8. 如果喫單者的ERC20合約調用失敗,則整個交易回滾。
  9. 交易從代理返回到兌換合約。
  10. 返回交易執行結果

接下來,我們將討論使用0x.js庫在以太坊上的部署0x智能合約,以便交易資產,使用 npm 安裝0x.js:

npm install 0x.js

部署0x智能合約

要與智能合約進行交互,我們需要部署0x智能合約,然後通過 0x.js庫用合約地址與合約進行交互。

資產兌換合約

資產兌換合約的源代碼在 此github ,資產兌換合約構造函數沒有參數,部署的時候不需要提供參數,部署者(msg.sender)將是合約的所有者(Owner)。所有者能夠在兌換合約中設置代理合約的地址。

ERC20代理合約

使用ERC20代理合約的 源代碼 進行部署,代理合約的構造函數不需要參數,部署者(msg.sender)將是合約的所有者。所有者將能夠在ERC20代理合約中設置資產兌換合約的地址。

ERC721代理合約

使用 ERC721代理合約 源代碼 進行部署,代理合約的構造函數不需要參數,部署者(msg.sender)將是合約的所有者。所有者將能夠在ERC721代理合約中設置資產兌換合約的地址。

與 0x 協議交互

與0x交互的最終目標是掛單者使用0x.js庫創建訂單,喫單者使用fillOrder()函數提交訂單進行兌換。

註冊合約

部署完以上合約後,需要在資產代理合約中設置兌換合約的地址,在兌換合約中設置資產代理合約的地址。

  • 調用資產兌換合約的 registerAssetProxy(ERC20 或 ERC71 代理合約地址) 方法將記錄資產代理合約的地址,兌換代幣交易是在代理合約中進行的。該方法只能由資產交換智能合約的所有者調用。

  • 調用ERC20代理合約的 addAuthorizedAddress(兌換合約) 方法註冊兌換合約。

  • 調用ERC20代理合約的 removeAuthorizedAddress(兌換地址) 方法刪除兌換合約。

合約配置

使用資產兌換合約和資產代理合約地址通過0x.js庫 進行交互 :

let contractConfig = {
  contractAddresses: {
    erc20Proxy: proxyAddress.toLowerCase(),
    erc721Proxy: "0x1d7022f5b17d2f8b695918fb48fa1089c9f85401",
    exchange: exchangeAddress.toLowerCase() 
  },
  networkId: networkId
};

const contractWrappers = new ContractWrappers(holderEngine, contractConfig);

現在就可以與部署在專用或測試網絡上的0x協議智能合約進行交互。 請記住添加RPC節點提供者以便與區塊鏈進行交互。

實例化

爲了與0x.js庫進行交互,我們需要導入(import)如下所示相關的軟件包

const {
  assetDataUtils,BigNumber,ContractWrappers,
  generatePseudoRandomSalt,orderHashUtils,signatureUtils
} = require('0x.js');

const TX_DEFAULTS = { gas: 400000 };
const { RPCSubprovider, Web3ProviderEngine } = require('0x.js');

let newWallet = new ethers.Wallet(wallet.signingKey.privateKey, prov);
const holderWallet = new PrivateKeyWalletSubprovider(wallet.signingKey.privateKey.slice(2));

添加RPC訂閱節點提供者:

const holderEngine = new Web3ProviderEngine();
holderEngine.addProvider(holderWallet);
// 訂閱節點提供者可以使用自定義URL分別連接以太坊主網、測試網或私鏈。
holderEngine.addProvider(new RPCSubprovider(providerUrl));
holderEngine.start();

獲取0x合約地址並實例化合約包裝器:

const contractWrappers = new ContractWrappers(holderEngine, contractConfig);
const web3Wrapper = new Web3Wrapper(providerEngine);
const contractAddresses = getContractAddressesForNetworkOrThrow(100);//networkID

ERC20合約授權

在掛單者(持有 tokenA)可以創建一個訂單並且喫單者(持有 token B)將提交訂單進行兌換之前,需要新進行授權。

先獲取相關合約地址:

// 合約地址
const tokenAAddress = contractAddresses.tokenA;
const tokenBAddress = contractAddresses.tokenB;
const exchange = contractAddresses.exchange;

所有地址都可以從0x.js庫獲取到。

// 將有關資產的所有必要信息編碼爲十六進制字符串

const makerAssetData = assetDataUtils.encodeERC20AssetData(tokenAAddress);
const takerAssetData = assetDataUtils.encodeERC20AssetData(tokenBAddress);
const makerAssetAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(100), DECIMALS);
const takerAssetAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(200), DECIMALS);
const NULL_ADDRESS = '0x0000000000000000000000000000000000000000';
const ZERO = new BigNumber(0);
const DECIMALS = 18;

現在掛單者和喫單者應該授權相應的資產代理合約,以便代理合約可以分別代表掛單者和喫單者轉移代幣:

// 授權
const makerApprovalTxHash = await contractWrappers.erc20Token.setUnlimitedProxyAllowanceAsync(
    tokenAAddress,
    maker,
);
await web3Wrapper.awaitTransactionSuccessAsync(makerApprovalTxHash);

// 授權
const takerApprovalTxHash = await contractWrappers.erc20Token.setUnlimitedProxyAllowanceAsync(
    tokenBAddress,
    taker,
);
await web3Wrapper.awaitTransactionSuccessAsync(takerApprovalTxHash);

在掛單者和喫單者授權資產代理合約之後,代理合約就可以分別代表掛單者和喫單者轉移代幣了。

接下來,掛單者將創建一個委託訂單並在鏈下簽名,而喫單者將在鏈上執行訂單。

創建訂單、驗證與喫單

創建訂單:

const order = {
  exchangeAddress: exchangeAddress,
  makerAddress: maker,//address of maker
  takerAddress: taker,//address of taker
  senderAddress: taker,// address of sender
  feeRecipientAddress: NULL_ADDRESS,//fee in the form of native currency of platform
  expirationTimeSeconds: randomExpiration,//訂單過期時間
  salt: generatePseudoRandomSalt(),// 隨機數,用來區分訂單
  makerAssetAmount,// 掛單資產數量
  takerAssetAmount,// taker asset amount
  makerAssetData,//encoded address of tokenA
  takerAssetData,//encoded address of tokenB
  makerFee: ZERO,//fee if required
  takerFee: ZERO,//fee if required
};

現在我們創建了一個資產交換委託訂單。接下來在調用0x.js庫的 getOrderHash() 函數獲得訂單哈希值以便進行簽名。這個哈希根據EIP712對訂單計算出來的:

const orderHashHex = orderHashUtils.getOrderHashHex(order);

獲取訂單的哈希後,掛單者使用0x.js庫的 ecSignHashAsync() 方法對訂單簽名。

const signature = await signatureUtils.ecSignHashAsync(providerEngine, orderHashHex, maker);
const signedOrder = { …order, signature };

喫單者可以使用資產交易合約的validateFillOrderThrowIfInvalidAsync`方法驗證訂單是否可以執行:

await contractWrappers.exchange.validateFillOrderThrowIfInvalidAsync(
  signedOrder, 
  takerAssetAmount, 
  taker
);

最終,喫單者調用資產交易合約的 fillOrderAsync 方法執行訂單:

try{
  txHash = await contractWrappers.exchange.fillOrderAsync(
    signedOrder, 
    takerAssetAmount, 
    taker, 
    {TX_DEFAULTS,}
  );

  var transaction = await web3Wrapper.awaitTransactionSuccessAsync(txHash);
}
catch(error){}

讓我們快速回顧一下到目前爲止所學到的知識,然後通過介紹已經建立在0x上的項目來結束我們的討論。

回顧

本文介紹了什麼是0x協議,其特點是什麼、它是如何工作的,以及如何掛單及喫單。

下面列出了已經使用0x協議實現DEX和訂單簿的項目。

DEX有: Radar Relay , paradex , Star bitex , LedgerDex

訂單簿有: open relay

原文鏈接: How to integrate 0x(ZRX) Protocol to setup your own Decentralized Exchange (DEX)

本文參與登鏈社區寫作激勵計劃 ,好文好收益,歡迎正在閱讀的你也加入。

  • 發表於 8分鐘前
  • 閱讀 ( 6 )
  • 學分 ( 0 )
  • 分類:DeFi
相關文章