使用PHP-SDK调用Soroban Smart Contracts功能
#php #smartcontract #soroban #stellar

在我的last post中,我试图向您展示如何使用Soroban Rust SDK编写和构建智能合同来参与投票过程。

在这篇文章中,我正在尝试展示如何使用Soroban PHP SDK的已部署和安装合同的Soroban智能合同函数。

有关部署和安装合同的更多信息,请参阅soroban docs

基础

在调用任何功能之前,我们必须获得一个 soneso \ stellarsdk \ soroban \ sorobanserver 的实例,这将使我们可以连接到Soroban RPC服务器并能够调用功能。


$server = new SorobanServer("https://rpc-futurenet.stellar.org:443");
$server->acknowledgeExperimental = true;
$server->enableLogging = true;

$healthResponse = $server->getHealth();
if (GetHealthResponse::HEALTHY == $healthResponse->status) {
    throw new \Exception("Server unavailable");
}

在上面可以看到的代码中,我们首先获得 sorobanserver 实例。然后,我们设置true标志 fackledgeExperimentiment enableLogging

  • wendledge Expermentiment 才能到目前为止工作。
  • enableLogging 将向我们显示呼叫日志。

现在我们有了服务器实例,让我们看看如何获​​取一个帐户调用功能。

在Futurenet上获取帐户

我们需要一个出色的帐户才能签署交易(调用智能合同功能是通过事务发送的出色操作)。要获得一个出色的帐户,我们需要一个钥匙对。您可以从stellar laboratory获得一个钥匙对。
假设我们已经有了钥匙对,让我们在php中获取账单案件。

$futurenet = StellarSDK::getFutureNetInstance();
$accountKeyPair = KeyPair::fromSeed('mysecretkey');
$account   = $futurenet->requestAccount($accountKeyPair->getAccountId());

您可以看到,只有三个代码行,我们可以获取账户实例:

  • 使用Soneso \ Stellarsdk \ Stellarsdk_ class
  • 获取Futurenet实例
  • 使用 soneso \ stellarsdk \ crypto \ keypair class
  • 获取密钥对实例
  • 最终通过帐户ID向Futurenet请求帐户

调用非身份验证功能

现在,我们有帐户和服务器实例,并假设我们以前已将合同部署到Futurnet并拥有合同ID,让我们调用一个非身份验证的功能:

我们在文章开始时引用的最后一篇文章的合同具有未接收参数的非身份验证函数,称为 count 。让我们尝试调用它。

$operation = InvokeHostFunctionOperationBuilder::forInvokingContract($contractId, 'count');
$transaction = (new TransactionBuilder($account))->addOperation($operation)->build();

$simulateResponse = $server->simulateTransaction($transaction);
$footprint = $simulateResponse->getFootprint();

$transaction->setFootprint($footprint);
$transaction->sign($accountKeyPair, Network::futurenet());

$sendResponse = $server->sendTransaction($transaction);
if ($sendResponse->error == null) {
     $result = null;
     $failedStatus = null;
     while (empty($result) && empty($failedStatus)) {
         $transactionResponse = $server->getTransaction($sendResponse->hash);
         if (GetTransactionResponse::STATUS_NOT_FOUND == $transactionResponse->status) {
              sleep(1);
         } 
         else if (GetTransactionResponse::STATUS_SUCCESS == $transactionResponse->status) {
              $result = $transactionResponse->getResultValue();
         } 
         else if (GetTransactionResponse::STATUS_FAILED == $transactionResponse->status) {
              $failedStatus = $transactionResponse->error->getMessage();
         }
     }

     if ($result) {
          foreach ($result->getMap() as $partyInfo) {
             echo 'Result for ' . $partyInfo->key->getSym() . ': ' . $partyInfo->val->getU32() . PHP_EOL;
          }
          return Command::SUCCESS;
     }

     if ($failedStatus) {
         echo 'Invokation has failed';
     }
}

让我们逐步研究代码

$operation = InvokeHostFunctionOperationBuilder::forInvokingContract($contractId, 'count');
$transaction = (new TransactionBuilder($account))->addOperation($operation)->build();

首先,我们创建了一个出色的操作,用于调用合同功能,然后将其添加到新事务中。

$simulateResponse = $server->simulateTransaction($transaction);
$footprint = $simulateResponse->getFootprint();

接下来,我们模拟交易并获得占地面积。我们将需要足迹来稍后发送交易。

$transaction->setFootprint($footprint);
$transaction->sign($accountKeyPair, Network::futurenet());

获得足迹后,我们将其设置为交易并签名。为了签署交易,我们需要以前获得的关键对实例。

$sendResponse = $server->sendTransaction($transaction);

我们准备好交易,因此我们使用服务器实例发送它。

if ($sendResponse->error == null) {
     $result = null;
     $failedStatus = null;
     while (empty($result) && empty($failedStatus)) {
         $transactionResponse = $server->getTransaction($sendResponse->hash);
         if (GetTransactionResponse::STATUS_NOT_FOUND == $transactionResponse->status) {
              sleep(1);
         } 
         else if (GetTransactionResponse::STATUS_SUCCESS == $transactionResponse->status) {
              $result = $transactionResponse->getResultValue();
         } 
         else if (GetTransactionResponse::STATUS_FAILED == $transactionResponse->status) {
              $failedStatus = $transactionResponse->error->getMessage();
         }
     }

     if ($result) {
         foreach ($result->getMap() as $partyInfo) {
            echo 'Result for ' . $partyInfo->key->getSym() . ': ' . $partyInfo->val->getU32() . PHP_EOL;
         }
         return Command::SUCCESS;
     }

     if ($failedStatus) {
         echo 'Invokation has failed';
     }
}

在最后一部分中,如果没有错误响应,我们进行以下操作:

  • 研究交易响应状态
  • 如果还没有找到交易,我们会等一秒钟,然后重试。
  • 如果交易成功,我们将获得结果值。
  • 如果交易失败,我们会收到失败的消息。

如果我们执行此代码,我们将获得以下结果:

Count function result

调用身份验证的功能

现在让我们看看如何调用 add_party 函数,需要两个参数:

  • 调用该功能的地址(将在合同部分进行身份验证)
  • 一个聚会可以添加到选票中
$invokerAddress = new Address(Address::TYPE_ACCOUNT, accountId: $account->getAccountId());
$argsContract[] = $invokerAddress->toXdrSCVal();
$argsContract[] = XdrSCVal::forSymbol('Laborist');

$authInvocation = new AuthorizedInvocation($contractId, $function, args: $argsContract);
$contractAuth = new ContractAuth($authInvocation);

$invokeOp = InvokeHostFunctionOperationBuilder::forInvokingContract($contractId, $function, $argsContract, auth: [$contractAuth])->build();

$transaction = (new TransactionBuilder($account))->addOperation($invokeOp)->build();
$simulateResponse = $server->simulateTransaction($transaction);

就像我们在上一节中所做的那样,让我们​​逐步研究代码:

$invokerAddress = new Address(Address::TYPE_ACCOUNT, accountId: $account->getAccountId());
$argsContract[] = $invokerAddress->toXdrSCVal();
$argsContract[] = XdrSCVal::forSymbol('Laborist');

$authInvocation = new AuthorizedInvocation($contractId, 'add_party', args: $argsContract);
$contractAuth = new ContractAuth($authInvocation);
  • 我们使用Soneso \ Stellarsdk \ Soroban \ Soloban \ class_ class。
  • 我们向ARGS合同添加地址和劳动党

参数是使用XDR编码的,这是Stellar使用的二进制格式,用于在网络上传达TransActions。

  • 我们创建一个授权的调用通过合同ID,函数名称和参数。然后,我们将其包装成合同的实例。

作为函数起义者和交易提交器相同,我们可以避免签署合同验证,因为它将从交易中推断出来。更多信息here

$invokeOp = InvokeHostFunctionOperationBuilder::forInvokingContract($contractId, $function, $argsContract, auth: [$contractAuth])->build();

$transaction = (new TransactionBuilder($account))->addOperation($invokeOp)->build();
$simulateResponse = $server->simulateTransaction($transaction);

现在,我们创建调用操作并首先模拟事务。

用于分析事务状态的代码与以前相同,所以让我们直接去获取函数响应

if($result) {
    echo 'Number of parties: ' . $result->getU32();
}

如果您查看ballot contract article,您会看到 add_party 功能返回合同中注册的当事方。

调用功能后,您会看到以下结果:

add_party_function_result

仅此而已,我希望它可以为您提供智能合同功能:)