PHP Algorand SDK 2.0 (algod, algokey, kmd, transactions and indexer)

April 10, 2023 · View on GitHub

A Pure PHP (no dependencies) library for interacting with the Algorand network.

All files in this directory will show you about the best pratices that you should do when implementing php-algorand-sdk into your project.

Requirements

  • PHP 7.3 and above.
  • Built-in libcurl support.
  • Algorand node, algod, kmd, indexer or PureStake

Frameworks Compatibility

This SDK was developed to support several PHP Frameworks, tested with:

  • Native Frameworks
  • FFS
  • Laravel
  • Lumen
  • Yii
  • Codeigniter
  • Symfony

In the sdk folder you will find the setup suggestions.

Quick start

For running this example, you need to install php-algorand-sdk library before, and start the node.

$ git clone https://github.com/ffsolutions/php-algorand-sdk
$ ./goal node start -d data
$ ./goal kmd start -d data
$ ./algorand-indexer daemon -h -d data

After cloning the repository, you need to include the php-algorand-sdk:

require_once 'sdk/algorand.php';
require_once 'sdk/algokey.php';

#OR with namespace include

use App\Algorand\algorand;
use App\Algorand\transactions;
use App\Algorand\algokey;
use App\Algorand\b32;
use App\Algorand\msgpack;

For use the algod:

# Node
$algorand = new Algorand("algod","{algod-token}","localhost",53898); //get the token key in data/algod.admin.token

# PureStake
$algorand = new Algorand("algod","{pure-stake-token}","mainnet-algorand.api.purestake.io/ps2",0,true); //External PureStake

$return=$algorand->get("v2","status");
print_r($return);

(see all avaliable functions in algod.php)

For use the kmd:

#Node only
$algorand_kmd = new  Algorand("kmd","{kmd-token}","localhost",7833); //get the token key in data/kmd-{version}/kmd.token and port in data/kmd-{version}/kmd.net
$return=$algorand_kmd->get("versions");
print_r($return);

(see all avaliable functions in kmd.php)

For use the indexer:

#Node
$algorand_indexer = new Algorand("indexer","{algorand-indexer-token}","localhost",8089);

#PureStake
$algorand_indexer = new Algorand("indexer","{pure-stake-token}","mainnet-algorand.api.purestake.io/idx2",0,true); //true for External PureStake

$return=$algorand_indexer->get("health");
print_r($return);

(see all avaliable functions in indexer.php)

For use the algokey:

$algokey=new  algokey;

$key=$algokey->generate();
print_r($key);

(see all avaliable functions in algokey.php)

For use the transactions:

$algorand_transactions = new  Algorand_transactions;
#Build and Sign a transaction, for details: https://developer.algorand.org/docs/features/transactions

#Payment Transaction (ALGO)

$transaction=array(
        "txn" => array(
                "type" => "pay", //Tx Type
                "fee" => 1000, //Fee
                "fv" => 27151092, //First Valid
                "gen" => "mainnet-v1.0", // GenesisID
                "gh" => "wGHE2Pwdvd7S12BL5FaOP20EGYesN73ktiC1qzkkit8=", //Genesis Hash
                "lv" => 27152092, //Last Valid
                "note" => "Testes", //You note
                "snd" => "3DKZLYQJXSUAE7ZCFZN7ODZSOA6733PI5BFM4L7WI4S3K6KEVOOA6KDN2I", //Sender
                "rcv" => "IYVZLDFIF6KUMSDFVIKHPBT3FI5QVZJKJ6BPFSGIJDUJGUUASKNRA4HUHU", //Receiver
                "amt" => 1000, //Amount
            ),
);

(see all avaliable functions in transactions.php)

Vídeo Tutorial

PHP Algorand SDK Vídeo Tutorial

https://www.youtube.com/watch?v=7ZoDY6av1-4

Application Examples

See at examples folder.

https://github.com/ffsolutions/php-algorand-sdk/tree/main/examples

Algorand Wallet PHP GUI https://www.youtube.com/watch?v=Ju1f5MrwJKA

Algorand Asset Manager PHP GUI https://www.youtube.com/watch?v=b__DhRzAex0

Algorand Explorer PHP GUI https://www.youtube.com/watch?v=b__DhRzAex0

Complete Guide

Node setup (macOS and Linux)

Verified on macOS Monterey 12.5.1 and Ubuntu 22.04

For other cases, follow the instructions in Algorand's developer resources to install a node on your computer.

Steps:

  • 1- Installing Algorand Node
  • 2- Installing Algorand Indexer
  • 3- Installing and Using the PHP Algorand SDK

For macOS and Linux:

Create a temporary folder to hold the install package and files:

$ mkdir ~/node
$ cd ~/node

Download the updater script:

macOS

$ curl https://raw.githubusercontent.com/algorand/go-algorand/rel/stable/cmd/updater/update.sh -O

Linux

$ wget https://raw.githubusercontent.com/algorand/go-algorand/rel/stable/cmd/updater/update.sh

Ensure that your system knows it's an executable file:

$ chmod 744 update.sh

Run the installer from within your node directory:

$ ./update.sh -i -c stable -p ~/node -d ~/node/data -n

Create and change the config.json

$ cp data/config.json.example data/config.json
$ chmod 777 data/config.json
$ cp data/kmd-v{version}/kmd_config.json.example data/kmd-v{version}/kmd_config.json
$ chmod 777 data/kmd-v{version}/kmd_config.json
$ vim data/config.json

Change the line, press I to enable edition, make changes, press ESC and type :w + [enter], :q + [enter] to finish.

"EndpointAddress": "127.0.0.1:0",  
to
"EndpointAddress": "127.0.0.1:53898",

Start Node:

./goal node start -d data
./goal kmd start -d data
./algorand-indexer daemon -P "host=127.0.0.1 port=5432 user={user} password={password} dbname=algorand sslmode=disable"  --no-algod

To see if the node is running:

$ htop

Press F10 to close the htop

Sync Node Network using Fast Catchup

Fast Catchup is a new feature and will rapidly update a node using catchpoint snapshots. A new command on goal node is now available for catchup. The entire process should sync a node in minutes rather than hours or days.

Get the catchpoint

$ wget -qO- https://algorand-catchpoints.s3.us-east-2.amazonaws.com/channel/mainnet/latest.catchpoint

Use the sync point captured above and paste into the catchup option

./goal node catchup 12400000#ZHHAYEVVUXHMDVIRFUFQLI7DUUMJAEDCJN7WPG6OD4DRBBIWK5UA -d data

Node Status: ./goal node status -d data Results should show 5 Catchpoint status lines for Catchpoint, total accounts, accounts processed, total blocks , downloaded blocks. Notice that the 5 Catchpoint status lines will disappear when completed, and then only a few more minutes are needed so sync from that point to the current block. Once there is a Sync Time of 0, the node is synced and if fully usable.

Last committed block: 11494
Sync Time: 58.1s
Catchpoint: 12400000#ZHHAYEVVUXHMDVIRFUFQLI7DUUMJAEDCJN7WPG6OD4DRBBIWK5UA
Catchpoint total accounts: 9133629
Catchpoint accounts processed: 7786496
Catchpoint accounts verified: 0
Genesis ID: mainnet-v1.0
Genesis hash: wGHE2Pwdvd7S12BL5FaOP20EGYesN73ktiC1qzkkit8=

Installing the Algorand Indexer

For more details: https://developer.algorand.org/docs/run-a-node/setup/indexer/

Installing and Using the Algorand PHP SDK

Get the node tokens and address:

$ cat data/algod.token
$ cat data/kmd-{version}/kmd.token
$ cat data/kmd-{version}/kmd.net

Clone Git Hub Project

$ git clone https://github.com/ffsolutions/php-algorand-sdk.git

After cloning the repository, you need to include the php-algorand-sdk:

require_once 'sdk/algorand.php';
require_once 'sdk/algokey.php';
require_once 'sdk/transactions.php';

#OR with namespace include

use App\Algorand\algorand;
use App\Algorand\algokey;
use App\Algorand\transactions;
use App\Algorand\b32;
use App\Algorand\msgpack;

For use the Algokey:

Start the Algokey

$algokey=new  algokey;

Generate New Key/Account/Address

$key=$algokey->generate();
print_r($key);
echo "Words to string: ".implode(" ",$key['words'])."\n";

Words to Private Key and Public Key (Array)

$words=explode(" ","connect produce defense output sibling idea oil siege decline dentist faint electric method notice style cook unlock rice confirm host tone test vehicle able keen"); //2OEZACD77WSR5C2HFEHO2BYHQEATOGFIUW3REGKOGNPPNYPPLROHDU2CQE
$privateKey=$algokey->WordsToPrivateKey($words); //Array
$privateKey_decoded=base64_decode($privateKey);
$publicKey=$algokey->publicKeyFromPrivateKey($privateKey);
$publicKey_decoded=$algokey->publicKeyFromPrivateKey($privateKey,false);
echo "Private Key: ".$privateKey."\n";
echo "Private Key decoded: ".$privateKey_decoded."\n";
echo "Public Key B32: ".$publicKey."\n";
echo "Public Key decoded: ".$publicKey_decoded."\n";

Private Key to Words

$privateKey="eenqctbZ48E5E8jHoc6jdhTGW/q6L3BP7l3gJnJ+P17TiZAIf/2lHotHKQ7tBweBATcYqKW3EhlOM1724e9cXA==";
$return_words=$algokey->privateKeyToWords($privateKey);
print_r($return_words);
echo "Words: ".implode(" ",$return_words)."\n";

Sign Transaction with Algokey PHP

$transaction=array(
        "txn" => array(
                "type" => "pay", //Tx Type
                "fee" => 1000, //Fee
                "fv" => 28237321, //First Valid
                "gen" => "mainnet-v1.0", // GenesisID
                "gh" => "wGHE2Pwdvd7S12BL5FaOP20EGYesN73ktiC1qzkkit8=", //Genesis Hash
                "lv" => 28238321, //Last Valid
                "note" => "", //You note
                "snd" => "2QAXTOHQJQH6I4FM6RWUIISXKFJ2QA4NVWELMIJ5XAKZB4N4XIEX7F5KPU", //Sender
                "rcv" => "DI65FPLNUXOJJR47FDTIB5TNNIA5G4EZFA44RZMRBE7AA4D453OYD2JCW4", //Receiver
                "amt" => 1003, //Amount
            ),
);

$transaction_raw=$algorand_transactions->encode($transaction);
$signature=$algokey->sign($transaction_raw,$privateKey);

Broadcasts a raw transaction to the network.

$transaction_raw_signed=$algorand_transactions->encode($transaction,true,$signature);

$algorand = new Algorand("algod","4820e6e45f339e0026eaa2b74c2aa7d8735cbcb2db0cf0444fb492892e1c09b7","localhost",53898);
$params['transaction']=$transaction_raw_signed;
print_r($params);
$return=$algorand->post("v2","transactions",$params);
print_r($return);

For use the Algod:

Start the SDK

#Node
$algorand = new  Algorand("algod",'{algod-token}',"localhost",53898); //get the token key in data/algod.token

#PureStake
$algorand = new Algorand("algod","{pure-stake-token}","mainnet-algorand.api.purestake.io/ps2",0,true); //true for External PureStake

Get the versions

$return=$algorand->get("versions");

Gets the current node status.

$return=$algorand->get("v2","status");

Gets the node status after waiting for the given round.

$return=$algorand->get("v2","status","wait-for-block-after",{block});

Gets the genesis information.

return=$algorand->get("genesis");

Returns 200 (OK) if healthy.

$return=$algorand->get("health");

Return metrics about algod functioning.

$return=$algorand->get("metrics");

Gets the current swagger spec.

$return=$algorand->get("swagger.json");

Get account information and balances.

$return=$algorand->get("v2","accounts","{address}","?exclude=none&?format=json"); //?exclude=none or all. When set to all will exclude asset holdings, &format=json or msgpack (opcional, default json)

Get account information about a given app.

$return=$algorand->get("v2","accounts","{address}","applications","{application-id}");

Get account information about a given asset.

$return=$algorand->get("v2","accounts","{address}","assets","{asset-id}");

Get a list of unconfirmed transactions currently in the transaction pool by address.

$return=$algorand->get("v2","accounts","{address}","transactions","pending","?format=json&max=2");

Get application information.

$return=$algorand->get("v2","applications","{application-id}");

Get box information for a given application.

$return=$algorand->get("v2","applications","{application-id}","box","?name=");

Get all box names for a given application.

$return=$algorand->get("v2","applications","{application-id}","boxes","?max=");

Get asset information.

$return=$algorand->get("v2","assets","{asset-id}");

Get the block for the given round.

$return=$algorand->get("v2","blocks","{block}");

Get the block hash for the block on the given round.

$return=$algorand->get("v2","blocks","{block}","hash");

Gets a proof for a given light block header inside a state proof commitment

$return=$algorand->get("v2","blocks","{block}","lightheader","proof");

Get a proof for a transaction in a block.

$return=$algorand->get("v2","blocks","{round}","transactions","{txid}","proof");

Starts a catchpoint catchup. For the last catchpoint access: https://algorand-catchpoints.s3.us-east-2.amazonaws.com/channel/mainnet/latest.catchpoint

$return=$algorand->post("v2","catchup","{catchpoint}");

Aborts a catchpoint catchup.

$return=$algorand->delete("v2","catchup","{catchpoint}");

Get a LedgerStateDelta object for a given round

$return=$algorand->get("v2","deltas","{round}");

Get the current supply reported by the ledger.

$return=$algorand->get("v2","ledger","supply");

Returns the minimum sync round the ledger is keeping in cache.

$return=$algorand->get("v2","ledger","sync");

Removes minimum sync round restriction from the ledger.

$return=$algorand->delete("v2","ledger","sync");

Given a round, tells the ledger to keep that round in its cache.

$return=$algorand->post("v2","ledger","sync","{round}");

Add a participation key to the node

$params['body']="{participationkey}";
$return=$algorand->post("v2","participation",$params);

Return a list of participation keys

$return=$algorand->get("v2","participation");

Append state proof keys to a participation key

$params['body']="{keymap}";
$return=$algorand->post("v2","participation","{participation-id}",$params);

Get participation key info given a participation ID

$return=$algorand->get("v2","participation","{participation-id}");

Delete a given participation key by ID

$return=$algorand->delete("v2","participation","{participation-id}");

Special management endpoint to shutdown the node. Optionally provide a timeout parameter to indicate that the node should begin shutting down after a number of seconds.

$params['params']=array("timeout" => 0);
$return=$algorand->post("v2","shutdown", $params);

Get a state proof that covers a given round

$return=$algorand->get("v2","stateproofs","{round}");

Compile TEAL source code to binary, produce its hash

$params['body']="";
$return=$algorand->post("v2","teal","compile",$params);

Disassemble program bytes into the TEAL source code.

$params['body']="";
$return=$algorand->post("v2","teal","disassemble",$params);

Provide debugging information for a transaction (or group).

$params['$params']=array(
                        "accounts" => array(), //Account
                        "apps" => array(), //Application
                        "latest-timestamp" => 0, //integer
                        "protocol-version" => "", //string
                        "round" => 0, //integer
                        "sources" => array(), //DryrunSource
                        "txns" => "", //string (json) > array
                   );
$return=$algorand->post("v2","teal","dryrun",$params);

Broadcasts a raw transaction to the network.

#Generate and Sign the transaction with cli or this sdk:
//CLI sample
#./goal clerk send -a 1000 -f {address_from} -t {address_to} -d data -o transactions/tran.txn
#./goal clerk sign --infile="trans/tran.txn" --outfile="trans/tran.stxn" -d data


$params['file']="transactions/tran.stxn";
$params['transaction']="";
$return=$algorand->post("v2","transactions",$params);

Get parameters for constructing a new transaction

$return=$algorand->get("v2","transactions","params");

Get a list of unconfirmed transactions currently in the transaction pool.

$return=$algorand->get("v2","transactions","pending","?format=json&max=2");

Get a specific pending transaction.

$return=$algorand->get("v2","transactions","pending","{txid}","?format=json");

For more details: https://developer.algorand.org/docs/reference/rest-apis/algod/v2/

For use the KMD:

Start the SDK

$algorand_kmd = new  Algorand("kmd","{kmd-token}","localhost",7833); //get the token key in data/kmd-{version}/kmd.token and port in data/kmd-{version}/kmd.net

$algorand_transactions = new  Algorand_transactions;

Get Versions

$return=$algorand_kmd->get("versions");

Get swagger.json

$return=$algorand_kmd->get("swagger.json");

Create Wallet

$params['params']=array(
    "wallet_name" => "",
    "wallet_password" => "",
    "wallet_driver_name" => "sqlite",
);
$return=$algorand_kmd->post("v1","wallet",$params);

Wallet List

$return=$algorand_kmd->get("v1","wallets");

Wallet Init

$params['params']=array(
    "wallet_id" => "",
    "wallet_password" => "",
);
$return=$algorand_kmd->post("v1","wallet","init",$params);
$return_array=json_decode($return['response']);
$wallet_handle_token=$return_array->wallet_handle_token;

Wallet Info

$params['params']=array(
    "wallet_handle_token" => $wallet_handle_token,
);
$return=$algorand_kmd->post("v1","wallet","info",$params);

Wallet Rename

$params['params']=array(
    "wallet_id" => "",
    "wallet_name" => "",
    "wallet_password" => "",
);
$return=$algorand_kmd->post("v1","wallet","rename",$params);

Wallet Handle Token Release

$params['params']=array(
    "wallet_handle_token" => $wallet_handle_token,
);
$return=$algorand_kmd->post("v1","wallet","release",$params);

Wallet Handle Token Renew

$params['params']=array(
    "wallet_handle_token" => $wallet_handle_token,
);
$return=$algorand_kmd->post("v1","wallet","renew",$params);

Generate a key

$params['params']=array(
    "display_mnemonic" => false,
    "wallet_handle_token" => $wallet_handle_token
);
$return=$algorand_kmd->post("v1","key",$params);

Delete a key

$params['params']=array(
    "address" => "",
    "wallet_handle_token" => $wallet_handle_token,
    "wallet_password" => ""
);
$return=$algorand_kmd->delete("v1","key",$params);

Export a key

$params['params']=array(
    "address" => "XI56XZXQ64QD7IO5UBRC2RBZP6TQHP5WEILLFMBTKPXRKK7343R3KZAWNQ",
    "wallet_password" => "testes",
    "wallet_handle_token" => $wallet_handle_token
);
$return=$algorand_kmd->post("v1","key","export",$params);

$export=json_decode($return['response']);

require_once 'sdk/algokey.php';
$algokey=new algokey;

$words=$algokey->privateKeyToWords($export->private_key);

print_r($words);

Import a key

require_once 'sdk/algokey.php';

$algokey=new algokey;
$words="ripple trap smoke crop name donor sun actor wreck disease mushroom sweet because phrase involve sail umbrella control swing uncle card phrase human absent marble";
$words_array=explode(" ",$words);

$privatekey=$algokey->WordsToprivateKey($words_array);

$params['params']=array(
    "private_key" => $privatekey,
    "wallet_handle_token" => $wallet_handle_token
);
$return=$algorand_kmd->post("v1","key","import",$params);

List keys in wallet

$params['params']=array(
    "wallet_handle_token" => $wallet_handle_token
);
$return=$algorand_kmd->post("v1","key","list",$params);

Master Key export

$params['params']=array(
    "wallet_password" => "",
    "wallet_handle_token" => $wallet_handle_token
);
$return=$algorand_kmd->post("v1","master-key","export",$params);

Delete a multisig

$params['params']=array(
    "address" => "",
    "wallet_handle_token" => $wallet_handle_token,
    "wallet_password" => ""
);
$return=$algorand_kmd->delete("v1","multisig",$params);

Export a multisig

$params['params']=array(
    "address" => "",
    "wallet_handle_token" => $wallet_handle_token
);
$return=$algorand_kmd->post("v1","multisig","export",$params);

Import a multisig

$params['params']=array(
    "multisig_version" => "1",
    "pks" => array(''),
    "threshold" => 1,
    "wallet_handle_token" => $wallet_handle_token
);
$return=$algorand_kmd->post("v1","multisig","import",$params);

List multisig in wallet

$params['params']=array(
    "wallet_handle_token" => $wallet_handle_token
);
$return=$algorand_kmd->post("v1","multisig","list",$params);

Sign a multisig transaction

$params['params']=array(
    "partial_multisig" => array(
                                "Subsigs" => array(
                                                    "Key" => array(),
                                                    "Sig" => array(),
                                ),
                                "Threshold" => 1,
                                "Version" => 1
                          ),
    "public_key" => array(''),
    "signer" => array(''),
    "transaction" => "",
    "wallet_handle_token" => $wallet_handle_token,
    "wallet_password" => ""
);
$return=$algorand_kmd->post("v1","multisig","sign",$params);

Sign a program for a multisig account

$params['params']=array(
    "address" => "",
    "data" => "",
    "partial_multisig" => array(
                                "Subsigs" => array(
                                                    "Key" => array(),
                                                    "Sig" => array(),
                                ),
                                "Threshold" => 1,
                                "Version" => 1
                          ),
    "public_key" => array(''),
    "wallet_handle_token" => $wallet_handle_token,
    "wallet_password" => ""
);
$return=$algorand_kmd->post("v1","multisig","signprogram",$params);

Sign program

$params['params']=array(
    "address" => "",
    "data" => "",
    "wallet_handle_token" => $wallet_handle_token,
    "wallet_password" => ""
);
$return=$algorand_kmd->post("v1","program","sign",$params);

For use Transactions:

To sign with Algokey load the Private Key

$words=explode(" ","connect produce defense output sibling idea oil siege decline dentist faint electric method notice style cook unlock rice confirm host tone test vehicle able keen"); //2OEZACD77WSR5C2HFEHO2BYHQEATOGFIUW3REGKOGNPPNYPPLROHDU2CQE
$privateKey=$algokey->WordsToPrivateKey($words); //Array to load words

To sign with KMD load the Wallet

$algorand_kmd = new Algorand("kmd","{kmd-token}","localhost",7833); //get the token key in data/kmd-{version}/kmd.token and port in data/kmd-{version}/kmd.net

#Wallet Init  //Only if you will use the KMD.
$params['params']=array(
    "wallet_id" => "",
    "wallet_password" => "tests",
);
$return=$algorand_kmd->post("v1","wallet","init",$params);
$return_array=json_decode($return['response']);
$wallet_handle_token=$return_array->wallet_handle_token;

Build and Sign a transaction

For details: https://developer.algorand.org/docs/features/transactions

Types:

appl = ApplicationCallTx allows creating, deleting, and interacting with an application

cert = CompactCertTx records a compact certificate

keyreg = KeyRegistrationTx indicates a transaction that registers participation keys

acfg = AssetConfigTx creates, re-configures, or destroys an asset

axfer = AssetTransferTx transfers assets between accounts (optionally closing)

afrz = AssetFreezeTx changes the freeze status of an asset

pay = PaymentTx indicates a payment transaction

Build Transaction

Application Call Transaction

$transaction=array(
        "txn" => array(
                "type" => "appl", //Tx Type
                "snd" => "DI65FPLNUXOJJR47FDTIB5TNNIA5G4EZFA44RZMRBE7AA4D453OYD2JCW4", //Sender
                "fee" => 1000, //Fee
                "fv" => 13029982, //First Valid
                "lv" => 13023082, //Last Valid
                "gh" => "wGHE2Pwdvd7S12BL5FaOP20EGYesN73ktiC1qzkkit8=", //Genesis Hash
                "apid" => "", //Application ID or empty if creating
                "apan" => "", //OnComplete
                "apat" => "", //Accounts
                "apap" => "", //Approval Program
                "apaa" => "", //App Arguments
                "apsu" => "", //Clear State Program
                "apfa" => "", //Foreign Apps
                "apas" => "", //Foreign Assets
                "apgs" => array( //GlobalStateSchema
                            "nui" => "", //Number Ints
                            "nbs" => "", //Number Byteslices
                        ),
                "apls" => array( //LocalStateSchema
                            "nui" => "", //Number Ints
                            "nbs" => "", //Number Byteslices
                        ),
            ),
);

Compact Certificate

$transaction=array(
        "txn" => array(
                "type" => "cert", //Tx Type
                "snd" => "DI65FPLNUXOJJR47FDTIB5TNNIA5G4EZFA44RZMRBE7AA4D453OYD2JCW4", //Sender
                "fee" => 1000, //Fee
                "fv" => 13029982, //First Valid
                "lv" => 13023082, //Last Valid
                "gh" => "wGHE2Pwdvd7S12BL5FaOP20EGYesN73ktiC1qzkkit8=", //Genesis Hash
                "certrnd" => "", //Round
                "certtype" => "", //CompactCertType
                "cert" => "", //Cert
            ),
);

Register account online

$transaction=array(
        "txn" => array(
                "type" => "keyreg", //Tx Type
                "selkey" => "X84ReKTmp+yfgmMCbbokVqeFFFrKQeFZKEXG89SXwm4=", //SelectionPK
                "fee" => 1000, //Fee
                "fv" => 13009389, //First Valid
                "gh" => "wGHE2Pwdvd7S12BL5FaOP20EGYesN73ktiC1qzkkit8=", //Genesis Hash
                "lv" => 13009489, //Last Valid
                "votefst" => 13009489, //VoteFirst
                "votelst" => 13009589, //VoteLast
                "votekd" => 1730, //VoteKeyDilution
                "votekey" => "eXq34wzh2UIxCZaI1leALKyAvSz/+XOe0wqdHagM+bw=",
                "snd" => "DI65FPLNUXOJJR47FDTIB5TNNIA5G4EZFA44RZMRBE7AA4D453OYD2JCW4", //Sender
            ),
);

Register account offline

$transaction=array(
        "txn" => array(
                "type" => "keyreg", //Tx Type
                "fee" => 1000, //Fee
                "fv" => 13009389, //First Valid
                "gh" => "wGHE2Pwdvd7S12BL5FaOP20EGYesN73ktiC1qzkkit8=", //Genesis Hash
                "lv" => 13009489, //Last Valid
                "snd" => "DI65FPLNUXOJJR47FDTIB5TNNIA5G4EZFA44RZMRBE7AA4D453OYD2JCW4", //Sender
            ),
);

Close an Account

$transaction=array(
        "txn" => array(
                "type" => "pay", //Tx Type
                "close" => "EW64GC6F24M7NDSC5R3ES4YUVE3ZXXNMARJHDCCCLIHZU6TBEOC7XRSBG4",
                "fee" => 1000, //Fee
                "fv" => 13009389, //First Valid
                "lv" => 13009489, //Last Valid
                "gen" => "mainnet-v1.0", // GenesisID
                "gh" => "wGHE2Pwdvd7S12BL5FaOP20EGYesN73ktiC1qzkkit8=", //Genesis Hash
                "note" => "Testes", //You note
                "snd" => "DI65FPLNUXOJJR47FDTIB5TNNIA5G4EZFA44RZMRBE7AA4D453OYD2JCW4", //Sender
                "rcv" => "EW64GC6F24M7NDSC5R3ES4YUVE3ZXXNMARJHDCCCLIHZU6TBEOC7XRSBG4", //Receiver
            ),
);

Create an Asset

$transaction=array(
        "txn" => array(
                "type" => "acfg", //Tx Type
                "snd" => "DI65FPLNUXOJJR47FDTIB5TNNIA5G4EZFA44RZMRBE7AA4D453OYD2JCW4", //Sender
                "fee" => 1000, //Fee
                "fv" => 13027977, //First Valid
                "lv" => 13028977, //Last Valid
                "gh" => "wGHE2Pwdvd7S12BL5FaOP20EGYesN73ktiC1qzkkit8=", //Genesis Hash
                "apar" => array( //AssetParams
                        //"am" => "", //MetaDataHash
                        "an" => "MyToken", //AssetName
                        "au" => "https://mytoken.site", //URL
                        "c" => "DI65FPLNUXOJJR47FDTIB5TNNIA5G4EZFA44RZMRBE7AA4D453OYD2JCW4", //ClawbackAddr
                        "dc" => 2, //Decimals
                        "f" => "DI65FPLNUXOJJR47FDTIB5TNNIA5G4EZFA44RZMRBE7AA4D453OYD2JCW4", //FreezeAddr
                        "m" => "DI65FPLNUXOJJR47FDTIB5TNNIA5G4EZFA44RZMRBE7AA4D453OYD2JCW4", //ManagerAddr
                        "r" => "DI65FPLNUXOJJR47FDTIB5TNNIA5G4EZFA44RZMRBE7AA4D453OYD2JCW4", //ReserveAddr
                        "t" => 100000000000, //Total
                        "un" => "MTK", //UnitName
                    ),

            ),
);

Reconfigure an Asset

$transaction=array(
        "txn" => array(
                "type" => "acfg", //Tx Type
                "snd" => "DI65FPLNUXOJJR47FDTIB5TNNIA5G4EZFA44RZMRBE7AA4D453OYD2JCW4", //Sender
                "fee" => 1000, //Fee
                "fv" => 13027977, //First Valid
                "lv" => 13028977, //Last Valid
                "gh" => "wGHE2Pwdvd7S12BL5FaOP20EGYesN73ktiC1qzkkit8=", //Genesis Hash
                "caid" => 185553584,
                "apar" => array( //AssetParams
                        "c" => "DI65FPLNUXOJJR47FDTIB5TNNIA5G4EZFA44RZMRBE7AA4D453OYD2JCW4", //ClawbackAddr
                        "f" => "DI65FPLNUXOJJR47FDTIB5TNNIA5G4EZFA44RZMRBE7AA4D453OYD2JCW4", //FreezeAddr
                        "m" => "DI65FPLNUXOJJR47FDTIB5TNNIA5G4EZFA44RZMRBE7AA4D453OYD2JCW4", //ManagerAddr
                        "r" => "DI65FPLNUXOJJR47FDTIB5TNNIA5G4EZFA44RZMRBE7AA4D453OYD2JCW4", //ReserveAddr
                    ),

            ),
);

Destroy an Asset

$transaction=array(
        "txn" => array(
                "type" => "acfg", //Tx Type
                "snd" => "DI65FPLNUXOJJR47FDTIB5TNNIA5G4EZFA44RZMRBE7AA4D453OYD2JCW4", //Sender
                "fee" => 1000, //Fee
                "fv" => 13027977, //First Valid
                "lv" => 13028977, //Last Valid
                "gh" => "wGHE2Pwdvd7S12BL5FaOP20EGYesN73ktiC1qzkkit8=", //Genesis Hash
                "caid" => 185553584, //ConfigAsset ID
            ),
);

Opt-in to an Asset

$transaction=array(
        "txn" => array(
                "type" => "axfer", //Tx Type
                "arcv" => "DOVA6TULHNY2DCS65LVT5QYLWZGM7WC2GISPRGNDWDUH3KUX56ZLQJW3AY", //AssetReceiver
                "snd" => "DOVA6TULHNY2DCS65LVT5QYLWZGM7WC2GISPRGNDWDUH3KUX56ZLQJW3AY", //Sender
                "fee" => 1000, //Fee
                "fv" => 13028464, //First Valid
                "lv" => 13028564, //Last Valid
                "gh" => "wGHE2Pwdvd7S12BL5FaOP20EGYesN73ktiC1qzkkit8=", //Genesis Hash
                "xaid" => 185553584, //XferAsset ID
            ),
);

Revoke an Asset

$transaction=array(
        "txn" => array(
                "aamt" => 100,
                "type" => "axfer", //Tx Type
                "arcv" => "DI65FPLNUXOJJR47FDTIB5TNNIA5G4EZFA44RZMRBE7AA4D453OYD2JCW4", //AssetReceiver
                "asnd" => "DOVA6TULHNY2DCS65LVT5QYLWZGM7WC2GISPRGNDWDUH3KUX56ZLQJW3AY", //AssetSender
                "snd" => "DI65FPLNUXOJJR47FDTIB5TNNIA5G4EZFA44RZMRBE7AA4D453OYD2JCW4", //Sender
                "fee" => 1000, //Fee
                "fv" => 13028982, //First Valid
                "lv" => 13029982, //Last Valid
                "gh" => "wGHE2Pwdvd7S12BL5FaOP20EGYesN73ktiC1qzkkit8=", //Genesis Hash
                "xaid" => 185553584, //XferAsset ID
            ),
);

Freeze an Asset

$transaction=array(
        "txn" => array(
                "afrz" => false,
                "type" => "afrz", //Tx Type
                "fadd" => "DOVA6TULHNY2DCS65LVT5QYLWZGM7WC2GISPRGNDWDUH3KUX56ZLQJW3AY", //FreezeAccount
                "snd" => "DI65FPLNUXOJJR47FDTIB5TNNIA5G4EZFA44RZMRBE7AA4D453OYD2JCW4", //Sender
                "fee" => 1000, //Fee
                "fv" => 13029982, //First Valid
                "lv" => 13023082, //Last Valid
                "gh" => "wGHE2Pwdvd7S12BL5FaOP20EGYesN73ktiC1qzkkit8=", //Genesis Hash
                "faid" => 185553584, //FreezeAsset
            ),
);

Transfer an Asset

$transaction=array(
        "txn" => array(
                "aamt" => 100,
                "type" => "axfer", //Tx Type
                "arcv" => "DI65FPLNUXOJJR47FDTIB5TNNIA5G4EZFA44RZMRBE7AA4D453OYD2JCW4", //AssetReceiver
                "snd" => "DOVA6TULHNY2DCS65LVT5QYLWZGM7WC2GISPRGNDWDUH3KUX56ZLQJW3AY", //Sender
                "fee" => 1000, //Fee
                "fv" => 13028982, //First Valid
                "lv" => 13029982, //Last Valid
                "gh" => "wGHE2Pwdvd7S12BL5FaOP20EGYesN73ktiC1qzkkit8=", //Genesis Hash
                "xaid" => 185553584, //XferAsset ID
            ),
);

Payment Transaction (ALGO)

$transaction=array(
        "txn" => array(
                "type" => "pay", //Tx Type
                "fee" => 1000, //Fee
                "fv" => 13009389, //First Valid
                "gen" => "mainnet-v1.0", // GenesisID
                "gh" => "wGHE2Pwdvd7S12BL5FaOP20EGYesN73ktiC1qzkkit8=", //Genesis Hash
                "lv" => 13009489, //Last Valid
                "note" => "Testes", //You note
                "snd" => "DI65FPLNUXOJJR47FDTIB5TNNIA5G4EZFA44RZMRBE7AA4D453OYD2JCW4", //Sender
                "rcv" => "IYVZLDFIF6KUMSDFVIKHPBT3FI5QVZJKJ6BPFSGIJDUJGUUASKNRA4HUHU", //Receiver
                "amt" => 1000, //Amount
            ),
);

Sign Transaction

$params['params']=array(
   "transaction" => $algorand_kmd->txn_encode($transaction),
   "wallet_handle_token" => $wallet_handle_token,
   "wallet_password" => "testes"
);

$return=$algorand_kmd->post("v1","transaction","sign",$params);
$r=json_decode($return['response']);
$txn=base64_decode($r->signed_transaction);
echo $txn;

Broadcasts a raw transaction to the network.

$algorand = new Algorand_algod('{algod-token}',"localhost",53898);
$params['transaction']=$txn;
$return=$algorand->post("v2","transactions",$params);
$txId=$return['response']->txId;
echo "txId: $txId";

For more details: https://developer.algorand.org/docs/reference/rest-apis/kmd/

Atomic Transfers

Create Transactions

$transactions=array();

//Transaction 1
$transactions[]=array(
        "txn" => array(
                "type" => "pay", //Tx Type
                "fee" => 1000, //Fee
                "fv" => 28259644, //First Valid
                "gen" => "mainnet-v1.0", // GenesisID
                "gh" => "wGHE2Pwdvd7S12BL5FaOP20EGYesN73ktiC1qzkkit8=", //Genesis Hash
                "lv" => 28260644, //Last Valid
                "note" => "Testes", //You note
                "snd" => "3DKZLYQJXSUAE7ZCFZN7ODZSOA6733PI5BFM4L7WI4S3K6KEVOOA6KDN2I", //Sender
                "rcv" => "DI65FPLNUXOJJR47FDTIB5TNNIA5G4EZFA44RZMRBE7AA4D453OYD2JCW4", //Receiver
                "amt" => 102, //Amount
            ),
);

//Transaction 2
$transactions[]=array(
        "txn" => array(
                "type" => "pay", //Tx Type
                "fee" => 1000, //Fee
                "fv" => 28259644, //First Valid
                "gen" => "mainnet-v1.0", // GenesisID
                "gh" => "wGHE2Pwdvd7S12BL5FaOP20EGYesN73ktiC1qzkkit8=", //Genesis Hash
                "lv" => 28260644, //Last Valid
                "note" => "Testes 2", //You note
                "snd" => "3DKZLYQJXSUAE7ZCFZN7ODZSOA6733PI5BFM4L7WI4S3K6KEVOOA6KDN2I", //Sender
                "rcv" => "DI65FPLNUXOJJR47FDTIB5TNNIA5G4EZFA44RZMRBE7AA4D453OYD2JCW4", //Receiver
                "amt" => 203, //Amount
            ),
);

Group Transactions

$groupid=$algorand_transactions->groupid($transactions);

#Assigns Group ID
$transactions[0]['txn']['grp']=$groupid;
$transactions[1]['txn']['grp']=$groupid;

Sign Transactions with Algokey

#Sign Transaction 1

$txn="";
$transaction_raw=$algorand_transactions->encode($transactions[0]);
$signature=$algokey->sign($transaction_raw,$privateKey);
$txn.=$algorand_transactions->encode($transactions[0],true,$signature);

#Sign Transaction 2
$transaction_raw=$algorand_transactions->encode($transactions[1]);
$signature=$algokey->sign($transaction_raw,$privateKey);
$txn.=$algorand_transactions->encode($transactions[1],true,$signature);

OR

Sign Transactions with KMD

#Sign Transaction 1
$txn="";
$params['params']=array(
   "transaction" => $algorand_transactions->encode($transactions[0]),
   "wallet_handle_token" => $wallet_handle_token,
   "wallet_password" => "tests",
);

$return=$algorand_kmd->post("v1","transaction","sign",$params);
$r=json_decode($return['response']);
$txn.=base64_decode($r->signed_transaction);


#Sign Transaction 2
$params['params']=array(
   "transaction" => $algorand_transactions->encode($transactions[1]),
   "wallet_handle_token" => $wallet_handle_token,
   "wallet_password" => "tests",
);
$return=$algorand_kmd->post("v1","transaction","sign",$params);
$r=json_decode($return['response']);
$txn.=base64_decode($r->signed_transaction);;

Send Transaction Group

#Broadcasts a raw atomic transaction to the network.
$algorand = new Algorand("algod","4820e6e45f339e0026eaa2b74c2aa7d8735cbcb2db0cf0444fb492892e1c09b7","localhost",53898);
$params['transaction']=$txn;
$return=$algorand->post("v2","transactions",$params);
$txId=$return['response']->txId;
echo "txId: $txId";

For more details: https://developer.algorand.org/docs/features/atomic_transfers/

For use the Indexer:

Start the SDK

$algorand_indexer = new Algorand("indexer","{algorand-indexer-token}","localhost",8089);

Get health, Returns 200 if healthy.

$return=$algorand_indexer->get("health");

Search for accounts.

$query=http_build_query(array(
    //"application-id" => 0, //integer
    //"asset-id" => 0, //integer
    //"auth-addr" => "", //string
    //"currency-greater-than" => 0, //integer
    //"currency-less-than" => 0, //integer
    "limit" => 100, //integer
    //"next" => "", //string - previous return {next-token}
    //"round" => 0, //integer
));
$return=$algorand_indexer->get("v2","accounts?".$query);

Lookup account information.

$return=$algorand_indexer->get("v2","accounts","{account-id}");

Lookup account transactions.

$query=http_build_query(array(
    //"application-id" => 0, //integer
    "asset-id" => 0, //integer
    "after-time" => "", //string (date-time)
    "before-time" => "", //string (date-time)
    "currency-greater-than" => 0, //integer
    "currency-less-than" => 0, //integer
    "limit" => 100, //integer
    //"max-round" => 0, //integer
    //"min-round" => 0, //integer
    //"next" => "", //string - previous return {next-token}
    "note-prefix" => "", //string
    "rekey-to" => false, //boolean
    //"round" => "", //integer
    "sig-type" => "sig", //enum (sig, msig, lsig)
    "tx-type" => "pay", //enum (pay, keyreg, acfg, axfer, afrz, appl)
    "txid" => "", //string
));

$return=$algorand_indexer->get("v2","accounts","{account-id}","transactions?".$query);

Search for applications

$query=http_build_query(array(
    "application-id" => 0, //integer
    "limit" => 100, //integer
    //"next" => "", //string - previous return {next-token}
));
$return=$algorand_indexer->get("v2","applications?".$query);

Lookup application.

$return=$algorand_indexer->get("v2","applications","{application-id}");

Search for assets.

$query=http_build_query(array(
    //"asset-id" => 0, //integer
    //"creator" => 0, //integer
    "limit" => 100, //integer
    //"name" => "", //string
    //"next" => "", //string - previous return {next-token}
    //"unit" => "", //string
));
$return=$algorand_indexer->get("v2","assets?".$query);

Lookup asset information.

$return=$algorand_indexer->get("v2","assets","{asset-id}");

Lookup the list of accounts who hold this asset

$query=http_build_query(array(
    //"currency-greater-than" => 0, //integer
    //"currency-less-than" => 0, //integer
    "limit" => 100, //integer
    //"next" => "", //string - previous return {next-token}
    //"round" => "", //integer
));
$return=$algorand_indexer->get("v2","assets","{asset-id}","balances?".$query);

Lookup the list of accounts who hold this asset

$query=http_build_query(array(
    "address" => "", //string
    "address-role" => "", //enum (sender, receiver, freeze-target)
    "after-time" => "", //string (date-time)
    "before-time" => "", //string (date-time)
    "currency-greater-than" => 0, //integer
    //"currency-less-than" => 0 //integer
    "exclude-close-to" => false, //boolean
    "limit" => 100, //integer
    "max-round" => 0, //integer
    "min-round" => 0, //integer
    //"next" => "", //string - previous return {next-token}
    "note-prefix" => "", //string
    "rekey-to" => false, //boolean
    //"round" => "", //integer
    "sig-type" => "sig", //enum (sig, msig, lsig)
    "tx-type" => "pay", //enum (pay, keyreg, acfg, axfer, afrz, appl)
    "txid" => "", //string
));
$return=$algorand_indexer->get("v2","assets","{asset-id}","transactions".$query);

Lookup block.

$return=$algorand_indexer->get("v2","blocks","{round-number}");

Search for transactions.

$query=http_build_query(array(
    "address" => "", //string
    "address-role" => "sender", //enum (sender, receiver, freeze-target)
    "after-time" => "", //string (date-time)
    "application-id" => 0, //integer
    "asset-id" => 0, //integer
    "before-time" => "", //string (date-time)
    "currency-greater-than" => 0, //integer
    "currency-less-than" => 0, //integer
    "exclude-close-to" => "false", //boolean
    "limit" => "100", //integer
    "min-round" => 2466647, //integer
    "max-round" => 2566647, //integer
    "next" => "", //string - previous return {next-token}
    "note-prefix" => "", //string
    "rekey-to" => false, //boolean
    //"round" => 2566247, //integer
    "sig-type" => "sig", //enum (sig, msig, lsig)
    "tx-type" => "pay", //enum (pay, keyreg, acfg, axfer, afrz, appl)
    "txid" => "", //string
));

Lookup a single transaction.

$return=$algorand_indexer->get("v2","transactions","{txid}");

For more details: https://developer.algorand.org/docs/reference/rest-apis/indexer/

Full response with debug (json response)

print_r($return);

Only response array

print_r(json_decode($return['response']));

Only erros messages array

print_r(json_decode($return['message']));

Configurations

To enable Debug

$algorand->debug(1);

To enable SSL

$algorand->setSSL('/home/felipe/certificate.cert');

License

php-algorand-sdk is licensed under a MIT license. See the LICENSE file for details.

If you would like to donate to help maintain our online nodes, this and future projects, this is our ALGO (Algorand) Wallet: IYVZLDFIF6KUMSDFVIKHPBT3FI5QVZJKJ6BPFSGIJDUJGUUASKNRA4HUHU

Thank you!