自動分帳是不少平臺都會用到的支付功能。不少互聯網內容售賣平臺都會跟內容提供者分帳。好比:Apple 的 App Store 跟 App 開發者三七分紅。不少平臺都使用了支付寶、微信支付做爲支付手段,可是要同時實現給內容提供者分帳,倒是一件不太容易的事。使用 FIBOS 智能合約能夠很容易實現這個需求。javascript
文中代碼已在 GitHub 上開源。https://github.com/fengluo/fi...java
在 FIBOS 轉帳是經過 token 合約的extransfer
方法來實現的。extransfer
方法在執行的時候會給轉帳方帳戶和入帳方帳戶發送通知。因此用戶給平臺方帳戶轉帳的時候,平臺帳戶就會收到通知。因此總體業務邏輯以下:git
quantity: 10 FO memo: 內容提供者帳戶 quantity: 8 FO 用戶帳戶 -------------------> 平臺帳戶 ----------------> 內容提供者帳戶 extransfer 2/8 分紅 extransfer
memo
中填寫內容提供者的帳戶名。extransfer
方法的通知,而後作出分帳計算,給對應內容提供者的帳戶轉帳對應金額。總體邏輯很簡單,整個合約代碼邏輯差很少用20行就能夠寫完。github
FIBOS 的智能合約分爲 ABI 文件和 JS 合約兩部分。ABI 至關於合約接口,JS 合約則是功能實現。本案例目前沒有接口設計需求,不過 ABI 文件仍是合約不可缺乏的部分。因此咱們簡單建立一下就好。json
咱們先建立一個 contracts
文件夾,合約文件都會放在這裏。而後在此文件夾下,建立 subaccount.abi
文件,內容爲:微信
{ "version": "eosio::abi/1.0" }
JS 合約部分也沒有太複雜。在 contracts
文件夾下建立 subaccount.js
文件,代碼爲:ide
exports.on_extransfer = (from, to, quantity, memo) => { // 須要在開頭作一些判斷 if (to === action.receiver && action.is_account(memo)) { const num = parseInt(quantity.quantity.split(' ')[0]) // 假設咱們約定平臺方跟內容提供者是2/8分紅。 const subnum = (num * 0.8).toFixed(4); trans.send_inline('eosio.token', 'extransfer', { from: to, to: memo, quantity: { quantity: `${subnum} ${quantity.quantity.split(' ')[1]}`, contract: quantity.contract }, memo: 'sub account' }, [ { // 須要提供合約帳戶的 active 權限 actor: action.receiver, permission: 'active' } ]); } }
合約代碼開頭咱們須要作一些驗證。函數
memo
參數來放內容提供者的帳戶,因此咱們須要對此參數校驗一下該帳戶是否存在防止打錯。合約代碼中咱們使用 send_inline
調用 eosio.token
合約來執行轉賬操做。轉賬操做須要對應帳戶的 active
權限才能執行。爲了解決權限濫用問題,FIBOS 定義了一個特殊權限 eosio.code
。咱們須要在平臺合約帳戶中配置權限,在 active
權限下添加該合約帳戶的 eosio.code
受權。具體的配置操做會在下面說明。測試
爲方便測試,咱們在測試網 http://testnet.fibos.fo 上註冊三個帳戶。微信支付
helloworld11
helloworld22
helloworld33
咱們須要記錄這三個帳號的帳戶名以及公私鑰。以便下面的開發使用。建立一個統一的配置文件來記錄這些數據:
const config = { // 平臺合約帳戶的客戶端配置 client: { chainId: '68cee14f598d88d340b50940b6ddfba28c444b46cd5f33201ace82c78896793a', httpEndpoint: 'http://testnet.fibos.fo', keyProvider: 'PRIVATE_KEY_OF_helloworld33' }, // 用戶帳戶的客戶端配置 callClient:{ chainId: '68cee14f598d88d340b50940b6ddfba28c444b46cd5f33201ace82c78896793a', httpEndpoint: 'http://testnet.fibos.fo', keyProvider: 'PRIVATE_KEY_OF_helloworld11' }, // 平臺合約帳戶信息 contractAccount: { name: 'helloworld33', publicKey: 'PUBLIC_KEY_OF_helloworld33', privateKey: 'PRIVATE_KEY_OF_helloworld33' }, // 用戶帳戶信息 account1: { name: 'helloworld11', publicKey: 'PUBLIC_KEY_OF_helloworld11', privateKey: 'PRIVATE_KEY_OF_helloworld11' }, // 內容提供者帳戶信息 account2: { name: 'helloworld22', publicKey: 'PUBLIC_KEY_OF_helloworld22', privateKey: 'PRIVATE_KEY_OF_helloworld22' } } module.exports = config
在合約代碼中,咱們調用了 trans.send_inline
函數調用合約 eosio.token
來實現轉賬操做,可是轉賬操做是須要帳戶的 active
權限。因此咱們須要更新一下合約帳戶的權限,須要添加調用者的 eosio.code
受權到它的 active
權限。這個調用者天然也是這個合約帳戶。
const FIBOS = require('fibos.js'); const config = require('./config'); const fibosClient = FIBOS(config.client); let ctx = fibosClient.contractSync('eosio'); var r = ctx.updateauthSync({ account: config.contractAccount.name, permission: 'active', parent: 'owner', auth: { threshold: 1, keys: [{ key: config.contractAccount.publicKey, weight: 1 }], accounts: [{ permission: { // 將調用者帳號的 eosio.code 受權添加到它的 active 權限下。 actor: config.contractAccount.name, permission: 'eosio.code' }, weight: 1 }] } },{ authorization: `${config.contractAccount.name}@owner` //更改帳戶權限須要使用 owner 權限 }); console.log(r);
const FIBOS = require('fibos.js'); const config = require('./config'); const fibosClient = FIBOS(config.client); const fs = require('fs'); // setcode const jsCode = fs.readTextFile(`${__dirname}/contracts/subaccount.js`); fibosClient.setcodeSync(config.contractAccount.name, 0, 0, fibosClient.compileCode(jsCode)); // getcode const code = fibosClient.getCodeSync(config.contractAccount.name, true); console.log('code:', code); // setabi const abi = JSON.parse(fs.readTextFile(`${__dirname}/contracts/subaccount.abi`)); fibosClient.setabiSync(config.contractAccount.name, abi);
咱們先來寫一個腳本 account.js
來查看三個帳戶的餘額。
const FIBOS = require('fibos.js'); const config = require('./config'); const fibosClient = FIBOS(config.callClient); const account1 = fibosClient.getTableRowsSync(true, 'eosio.token', config.account1.name, 'accounts'); console.log(config.account1.name); console.log(account1); const account2 = fibosClient.getTableRowsSync(true, 'eosio.token', config.account2.name, 'accounts'); console.log(config.account2.name); console.log(account2); const contractAccount = fibosClient.getTableRowsSync(true, 'eosio.token', config.contractAccount.name, 'accounts'); console.log(config.contractAccount.name); console.log(contractAccount);
執行 fibos account.js
來查看三個帳戶信息。 目前咱們的帳戶尚未 FO,因此大體狀況是這樣的:
helloworld11
金額:0.0000 FO
helloworld22
金額:0.0000 FO
helloworld33
金額:0.0000 FO
測試網會自動給每一個帳戶發放10 EOS 的通證用以測試使用。帳戶中還並無 FO 通證。因此咱們再來寫一個兌換腳本,用1 EOS 換一點 FO 通證。
const FIBOS = require('fibos.js'); const config = require('./config'); const fibosClient = FIBOS(config.callClient); let ctx = fibosClient.contractSync('eosio.token'); const r = ctx.exchangeSync( config.account1.name, '1.0000 EOS@eosio', '0.0000 FO@eosio', 'exchange FO to EOS', { authorization: config.account1.name } ); console.log(r)
再次執行 fibos account.js
來查看帳戶信息。目前咱們的帳戶金額大體是這樣的:
helloworld11
金額:146.4245 FO
helloworld22
金額:0.0000 FO
helloworld33
金額:0.0000 FO
下面寫個腳本 transfer.js
來執行轉賬操做。
const FIBOS = require('fibos.js'); const config = require('./config'); const fibosClient = FIBOS(config.callClient); let ctx = fibosClient.contractSync('eosio.token'); const r = ctx.extransferSync( config.account1.name, // 用戶帳戶 config.contractAccount.name, // 平臺合約帳戶 '10.0000 FO@eosio', // 轉賬金額 config.account2.name, // 附言填寫內容提供者的帳戶名,平臺合約會給它分帳 { authorization: config.account1.name //提供用戶帳戶的受權 } ) console.log(r)
咱們要從用戶帳戶 account1
給平臺合約帳戶 account3
轉賬 10 FO。memo
參數爲要分紅的內容提供者帳戶 account2
。根據合約中定的2/8分紅,平臺合約帳戶 account3
將會分得2 FO,而內容提供者帳戶 account2
將會得到8 FO。
使用命令 fibos transfer.js
執行該腳本完成轉賬操做。
下面咱們再來看一下目前三個帳戶狀況。執行命令 fibos account.js
。三個帳戶金額大體以下。
helloworld11
金額:136.4245 FO
helloworld22
金額:8.0000 FO
helloworld33
金額:2.0000 FO
結果顯示,分帳帳戶和平臺合約帳戶如預期那樣得到8 FO 和2 FO。
綜上,咱們成功使用了智能合約實現了自動分帳。平臺方還能夠繼續根據本身業務須要定製本身的合約。
文中的代碼請參考:https://github.com/fengluo/fi...