すべてのプロダクト
Search
ドキュメントセンター

Blockchain as a Service:コントラクト インターフェイス

最終更新日:Jan 19, 2025

コントラクト関連の操作が頻繁に呼び出されるコントラクト プラットフォームの場合、BaaS は JS SDK を最適化して、コントラクト操作をより簡単かつ効率的に行えるようにしました。コントラクト関連の操作を使用する前に、ABI とバイトコードを理解する必要があります。詳細については、「Cloud IDE スマート コントラクト開発環境」をご参照ください。

以下の説明では、サンプルコードCreditManagerSolidity スマート コントラクト開発からのものです。JS SDK は、Solidity コンパイラである solc-js と一緒に使用できます。 solc-js の詳細については、「Solidity を使用したコントラクトのコンパイル」をご参照ください。

スマート コントラクト インスタンスの作成

コントラクト コードを実行して、スマート コントラクト インスタンスを作成できます。このスマート コントラクトをデプロイおよび呼び出すことができます。

リクエスト パラメーター

パラメーター

必須

タイプ

説明

name

true

string

ターゲット スマート コントラクトの名前。このコントラクトの ID は、コントラクト名のハッシュ値です。

abi

true

string

JSON 形式の ABI ベースの文字列。

vmType

false

string

スマート コントラクト プラットフォームは、Solidity と C++ の両方のコントラクト言語をサポートしています。 C++ で記述されたコントラクト インスタンスを初期化するには、このパラメーターを chain.WASM として構成します。このパラメーターは、デフォルトで chain.EVM として構成されます。

例 1

java script
const solc = require('@alipay/solc')
const contract = fs.readFileSync('. /CreditManager.sol', {encoding: 'ascii'})
// 2 番目のパラメーターを 1 に設定してコンパイルを開始します
const output = solc.compile(contract, 1)
const abi = JSON.parse(output.contracts[':CreditManager'].interface)
const bytecode = output.contracts[':CreditManager'].bytecode

// タイムスタンプを追加して、コントラクト名の ID が一意であることを確認します
const contractName = 'contract'+Date.now()
// スマート コントラクト インスタンスを初期化します
let myContract = chain.ctr.contract(contractName, abi)

例 2

Wasm バイトコードを使用して、C++ で記述されたコントラクトを初期化します。

java script
const wasm_code = fs.readFileSync('./contract/base.wasm')
const abi = fs.readFileSync('./contract/base.abi')
const bytecode = '0x'+wasm_code.toString('hex')

// タイムスタンプを追加して、コントラクト名の ID が一意であることを確認します
const contractName = 'contract'+Date.now()
// スマート コントラクト インスタンスを初期化します
let myContract = chain.ctr.contract(contractName, abi, chain.WASM)

スマート コントラクトのデプロイ

new 操作を呼び出して、スマート コントラクトをデプロイできます。

リクエスト パラメーター

パラメーター

必須

タイプ

説明

bytecode

true

string

ターゲット スマート コントラクトのバイトコード。バイトコードは、「0x」プレフィックスのない 16 進数形式です。

data

true

object

「from」や「parameters」などのフィールドが含まれています。

data フィールドの内容

フィールド

必須

タイプ

説明

from

true

string

構成する現在のアカウント名。

parameters

true

Array

スマート コントラクトに init() 関数が含まれており、この関数がパラメーター リストを必要とする場合、このリストは parameters フィールドを介して渡すことができます。

java script
const solc = require('@alipay/solc')
const contract = fs.readFileSync('. /CreditManager.sol', {encoding: 'ascii'})
// 2 番目のパラメーターを 1 に設定してコンパイルを開始します
const output = solc.compile(contract, 1)
const abi = JSON.parse(output.contracts[':CreditManager'].interface)
const bytecode = output.contracts[':CreditManager'].bytecode

// タイムスタンプを追加して、コントラクト名の ID が一意であることを確認します
const contractName = 'contract'+Date.now()
// スマート コントラクト インスタンスを初期化します
let myContract = chain.ctr.contract(contractName, abi) 
// スマート コントラクトをデプロイします。 init() 関数で必要なパラメーターを渡すことができます。
myContract.new(bytecode, {
  from: 'Tester001',
  // parameters: [param1, param2]
}, (err, contract, data) => {
  console.log(data)
})

スマート コントラクトの呼び出し

ターゲット コントラクト メソッドの名前を使用して、コントラクト メソッドを呼び出します。

リクエスト パラメーター

パラメーター

必須

タイプ

説明

parameters

false

未指定

特定のコントラクト メソッドのパラメーター リストを参照してください。パラメーターの数は、コントラクト メソッドによって異なります。

data

true

object

from フィールドが含まれています。

data フィールドの内容

フィールド

必須

タイプ

説明

from

true

string

構成する現在のアカウント名。

例 1

コントラクトのコールバック関数をデプロイするときにコントラクト メソッドを呼び出します:

java script
myContract.new(bytecode, {
  from: 'Tester001',
  // parameters: [param1, param2]
}, (err, contract, data) => {
  console.log(data)
  // Issue コントラクト メソッドを呼び出すときは、2 つのパラメーター (アカウント ID と数値) が必要です。
  myContract.Issue('0xc60a9d48105950a0cca07a4c6320b98c303ad42d694a634529e8e1a0a16fcdb5', 100 , { from: 'Tester001' }, (err, output, data) => {
    console.log('output is:', output)
  })
})

例 2

コントラクトがデプロイされた後に、コントラクト メソッドを呼び出します。複数のコントラクトがある場合、これらのコントラクトは同時に呼び出されます。呼び出しの依存関係が存在する場合は、コールバック関数を使用します。

java script
myContract.new(bytecode, {
  from: 'Tester001',
  // parameters: [param1, param2]
}, (err, contract, data) => {
  console.log(data)
})

// 「Issue」コントラクト メソッドを呼び出します
myContract.Issue('0xc60a9d48105950a0cca07a4c6320b98c303ad42d694a634529e8e1a0a16fcdb5', 100 , { from: 'Tester001' }, (err, output, data) => {
  console.log('output is:', output)
})

スマート コントラクトの更新

update 操作を呼び出して、ブロックチェーン上に存在するコントラクトを更新できます。スマート コントラクトの更新は慎重に行ってください。コントラクトの更新は、新しいコントラクトと古いコントラクトのデータ ストレージと互換性がある必要があります。通常の状況では、この更新機能を使用しないことをお勧めします。

リクエスト パラメーター

パラメーター

必須

タイプ

説明

bytecode

true

string

ターゲット スマート コントラクトのバイトコード。バイトコードは、0x プレフィックスのない 16 進数形式です。

data

true

object

空のオブジェクト。

コントラクトのコールバック関数をデプロイするときにコントラクト メソッドを呼び出します:

java script
myContract.update(bytecode, {}
, (err, contract, data) => {
  console.log('contract update result:', data)
})
説明

コントラクトを更新するには、コンパイルされた runtime バイトコードが必要です。このバイトコードは、Solidity コンパイラである solc コンパイラ--bin-runtime パラメーターを使用することで直接取得できます。これは、コンパイルされた --bin パラメーターのバイトコードのサブセットです。 runtime バイトコードは、ローカル コントラクトをデプロイすることによって取得することもできます。

コントラクトをデプロイするか、solc-js を使用してコントラクトを更新することで runtime バイトコードを取得します: JavaScript 構文では、solc-js はデフォルトで --bin パラメーターを使用してコントラクトをバイトコードにコンパイルします。このバイトコードは、コントラクトを更新するために直接使用することはできません。ただし、コントラクトのデプロイ後に取得された runtime バイトコードを使用して、コントラクトを更新できます。

説明

Solidity-0.4.24 バージョンにのみ適用されます。バージョン 0.6.4 以降については、Solidity コンパイラ (solc) を使用して runtime バイトコードを取得してください。

次のように solc-js を使用してスマート コントラクトを更新します。

  1. solc-js を使用してコントラクト A をコンパイルします

  2. スマート コントラクト A をデプロイします

  3. スマート コントラクト A を呼び出します

  4. スマート コントラクト コードを変更して、スマート コントラクト A' を取得します

  5. solc-js を使用してスマート コントラクト A' をコンパイルします

  6. スマート コントラクト A' をローカルにデプロイし、runtime バイトコードを取得します。

  7. A' runtime バイトコードを使用して、スマート コントラクト A を更新します。

  8. スマート コントラクト A を呼び出して、更新ステータスを確認します。

const solc = require('@alipay/solc')
const contract = fs.readFileSync('. /CreditManager.sol', {encoding: 'ascii'})
// 2 番目のパラメーターを 1 に設定してコンパイルを開始します
const output = solc.compile(contract, 1)
const abi = JSON.parse(output.contracts[':CreditManager'].interface)
const bytecode = output.contracts[':CreditManager'].bytecode

console.log('bytecode:', bytecode)
// タイムスタンプを追加して、コントラクト名の ID が一意であることを確認します
let contractName = 'contract'+Date.now()
let myContract = chain.ctr.contract(contractName, abi)

// solc-js によってコンパイルされたバイトコードを使用してコントラクトをアップグレードします
myContract.new(bytecode, {
  from: 'Tester001',
}, (err, contract, data) => {
  console.log('contract new:', data)
  myContract.Issue('0xc60a9d48105950a0cca07a4c6320b98c303ad42d694a634529e8e1a0a16fcdb5', 100 , { from: 'Tester001' }, (err, output, data) => {
    console.log('output1 is:', output)

    //CreditManager.sol という名前のコントラクトの計算ロジックを変更して、CreditManagerPro.sol という名前のコントラクトを取得します。コントラクト ストレージ定義は変更できないことに注意してください。
    //Issue メソッドで、`credit[account] += value;` を `credit[account] += value * 2;` に変更します
    const contract_pro = fs.readFileSync('. /CreditManagerPro.sol', {encoding: 'ascii'})
    // 2 番目のパラメーターを 1 に設定してコンパイルを開始します
    const output_pro = solc.compile(contract_pro, 1)
    const abi_pro = JSON.parse(output_pro.contracts[':CreditManager'].interface)
    const bytecode_pro = output_pro.contracts[':CreditManager'].bytecode
    myContract = chain.ctr.contract(contractName, abi_pro)

    myContract.new(bytecode_pro, {
      from: 'Tester001',
      local: true,  //コントラクトをローカルにデプロイして `runtime` バイトコードを取得します
      block_number: 0 //ジェネシス ブロックを使用してコントラクトをローカルにデプロイし、コントラクト ID の競合を回避します。
    }, (err, contract, data) => {
      console.log('local contract new result:', data)

      // 取得した `runtime` バイトコードを使用してコントラクトをアップグレードします
      myContract.update(data.receipt.output.replace('0x' + chain.EVM, ''), {
      }, (err, contract, data) => {
        console.log('contract update result:', data)

        // 更新されたコントラクトを呼び出してクレジットを発行します
        myContract.Issue('0xc60a9d48105950a0cca07a4c6320b98c303ad42d694a634529e8e1a0a16fcdb5', 100 , { from: 'Tester001' }, (err, output, data) => {
          console.log('output2 is:', output.toString())

          // ターゲット アカウントに発行されたクレジットを表示します。コントラクトが正常に更新された場合、結果は 300 になります。
          myContract.Query('0xc60a9d48105950a0cca07a4c6320b98c303ad42d694a634529e8e1a0a16fcdb5', { from: 'Tester001' }, (err, output, data) => {
            console.log('output3 is:', output.toString())
          })
        })
      })
    })
  })


})

結果:

...
contract update result: { msg_type: 63,
  sequence: 7,
  return_code: 0,
  group_id: '0x0000000000000000000000000000000000000000',
  receipt:
   { result: 0,
     gas_used: 28610,
     log_entry: [ [Object] ],
     output: '' },
  block_number: 86114,
  transaction_index: 0,
  api: 'QueryTransactionReceipt',
  txhash:
   '0x40a72b99ec64fca0e1cc5025920de086a2523b4761ea5020c0f43a5240dc754a' }
output2 is: true
output3 is: 300