├── .github └── workflows │ └── tests.yml ├── .gitignore ├── .php-cs-fixer.dist.php ├── CHANGELOG.md ├── LICENSE.md ├── README.md ├── composer.json ├── composer.lock ├── configure-skeleton.sh ├── docs └── api │ ├── classes │ ├── Rootsoft-Algorand-Algorand.html │ ├── Rootsoft-Algorand-AlgorandServiceProvider.html │ ├── Rootsoft-Algorand-Clients-AlgoExplorer.html │ ├── Rootsoft-Algorand-Clients-AlgodClient.html │ ├── Rootsoft-Algorand-Clients-AlgorandClient.html │ ├── Rootsoft-Algorand-Clients-IndexerClient.html │ ├── Rootsoft-Algorand-Clients-KmdClient.html │ ├── Rootsoft-Algorand-Clients-PureStake.html │ ├── Rootsoft-Algorand-Crypto-ByteConstBlock.html │ ├── Rootsoft-Algorand-Crypto-Ed25519PublicKey.html │ ├── Rootsoft-Algorand-Crypto-IntConstBlock.html │ ├── Rootsoft-Algorand-Crypto-LangSpec.html │ ├── Rootsoft-Algorand-Crypto-Logic.html │ ├── Rootsoft-Algorand-Crypto-LogicSignature.html │ ├── Rootsoft-Algorand-Crypto-MultiSignature.html │ ├── Rootsoft-Algorand-Crypto-MultiSignatureAddress.html │ ├── Rootsoft-Algorand-Crypto-MultisigSubsig.html │ ├── Rootsoft-Algorand-Crypto-Operation.html │ ├── Rootsoft-Algorand-Crypto-ProgramData.html │ ├── Rootsoft-Algorand-Crypto-Signature.html │ ├── Rootsoft-Algorand-Crypto-VarintResult.html │ ├── Rootsoft-Algorand-Exceptions-AlgorandException.html │ ├── Rootsoft-Algorand-Exceptions-ApiKeyException.html │ ├── Rootsoft-Algorand-Exceptions-InvalidRequestException.html │ ├── Rootsoft-Algorand-Exceptions-MnemonicException.html │ ├── Rootsoft-Algorand-Exceptions-NotFoundException.html │ ├── Rootsoft-Algorand-Exceptions-NotImplementedException.html │ ├── Rootsoft-Algorand-Exceptions-OverQueryLimitException.html │ ├── Rootsoft-Algorand-Exceptions-OverspendException.html │ ├── Rootsoft-Algorand-Exceptions-RequestDeniedException.html │ ├── Rootsoft-Algorand-Exceptions-WordListException.html │ ├── Rootsoft-Algorand-Facades-AlgorandFacade.html │ ├── Rootsoft-Algorand-Indexer-AlgorandIndexer.html │ ├── Rootsoft-Algorand-Indexer-Builders-AccountQueryBuilder.html │ ├── Rootsoft-Algorand-Indexer-Builders-ApplicationQueryBuilder.html │ ├── Rootsoft-Algorand-Indexer-Builders-AssetQueryBuilder.html │ ├── Rootsoft-Algorand-Indexer-Builders-TransactionQueryBuilder.html │ ├── Rootsoft-Algorand-Indexer-QueryBuilder.html │ ├── Rootsoft-Algorand-Indexer-Services-ManagesIndexerAccountsV2.html │ ├── Rootsoft-Algorand-Indexer-Services-ManagesIndexerApplicationsV2.html │ ├── Rootsoft-Algorand-Indexer-Services-ManagesIndexerAssetsV2.html │ ├── Rootsoft-Algorand-Indexer-Services-ManagesIndexerTransactionsV2.html │ ├── Rootsoft-Algorand-Indexer-Services-ManagesIndexerV2.html │ ├── Rootsoft-Algorand-KMD-Api-KmdApi.html │ ├── Rootsoft-Algorand-KMD-ApiException.html │ ├── Rootsoft-Algorand-KMD-Configuration.html │ ├── Rootsoft-Algorand-KMD-HeaderSelector.html │ ├── Rootsoft-Algorand-KMD-Model-APIV1DELETEKeyResponse.html │ ├── Rootsoft-Algorand-KMD-Model-APIV1DELETEMultisigResponse.html │ ├── Rootsoft-Algorand-KMD-Model-APIV1GETWalletsResponse.html │ ├── Rootsoft-Algorand-KMD-Model-APIV1POSTKeyExportResponse.html │ ├── Rootsoft-Algorand-KMD-Model-APIV1POSTKeyImportResponse.html │ ├── Rootsoft-Algorand-KMD-Model-APIV1POSTKeyListResponse.html │ ├── Rootsoft-Algorand-KMD-Model-APIV1POSTKeyResponse.html │ ├── Rootsoft-Algorand-KMD-Model-APIV1POSTMasterKeyExportResponse.html │ ├── Rootsoft-Algorand-KMD-Model-APIV1POSTMultisigExportResponse.html │ ├── Rootsoft-Algorand-KMD-Model-APIV1POSTMultisigImportResponse.html │ ├── Rootsoft-Algorand-KMD-Model-APIV1POSTMultisigListResponse.html │ ├── Rootsoft-Algorand-KMD-Model-APIV1POSTMultisigProgramSignResponse.html │ ├── Rootsoft-Algorand-KMD-Model-APIV1POSTMultisigTransactionSignResponse.html │ ├── Rootsoft-Algorand-KMD-Model-APIV1POSTProgramSignResponse.html │ ├── Rootsoft-Algorand-KMD-Model-APIV1POSTTransactionSignResponse.html │ ├── Rootsoft-Algorand-KMD-Model-APIV1POSTWalletInfoResponse.html │ ├── Rootsoft-Algorand-KMD-Model-APIV1POSTWalletInitResponse.html │ ├── Rootsoft-Algorand-KMD-Model-APIV1POSTWalletReleaseResponse.html │ ├── Rootsoft-Algorand-KMD-Model-APIV1POSTWalletRenameResponse.html │ ├── Rootsoft-Algorand-KMD-Model-APIV1POSTWalletRenewResponse.html │ ├── Rootsoft-Algorand-KMD-Model-APIV1POSTWalletResponse.html │ ├── Rootsoft-Algorand-KMD-Model-APIV1Wallet.html │ ├── Rootsoft-Algorand-KMD-Model-APIV1WalletHandle.html │ ├── Rootsoft-Algorand-KMD-Model-CreateWalletRequest.html │ ├── Rootsoft-Algorand-KMD-Model-DeleteKeyRequest.html │ ├── Rootsoft-Algorand-KMD-Model-DeleteMultisigRequest.html │ ├── Rootsoft-Algorand-KMD-Model-ExportKeyRequest.html │ ├── Rootsoft-Algorand-KMD-Model-ExportMasterKeyRequest.html │ ├── Rootsoft-Algorand-KMD-Model-ExportMultisigRequest.html │ ├── Rootsoft-Algorand-KMD-Model-GenerateKeyRequest.html │ ├── Rootsoft-Algorand-KMD-Model-ImportKeyRequest.html │ ├── Rootsoft-Algorand-KMD-Model-ImportMultisigRequest.html │ ├── Rootsoft-Algorand-KMD-Model-InitWalletHandleTokenRequest.html │ ├── Rootsoft-Algorand-KMD-Model-ListKeysRequest.html │ ├── Rootsoft-Algorand-KMD-Model-ListMultisigRequest.html │ ├── Rootsoft-Algorand-KMD-Model-ModelInterface.html │ ├── Rootsoft-Algorand-KMD-Model-MultisigSig.html │ ├── Rootsoft-Algorand-KMD-Model-MultisigSubsig.html │ ├── Rootsoft-Algorand-KMD-Model-ReleaseWalletHandleTokenRequest.html │ ├── Rootsoft-Algorand-KMD-Model-RenameWalletRequest.html │ ├── Rootsoft-Algorand-KMD-Model-RenewWalletHandleTokenRequest.html │ ├── Rootsoft-Algorand-KMD-Model-SignMultisigRequest.html │ ├── Rootsoft-Algorand-KMD-Model-SignProgramMultisigRequest.html │ ├── Rootsoft-Algorand-KMD-Model-SignProgramRequest.html │ ├── Rootsoft-Algorand-KMD-Model-SignTransactionRequest.html │ ├── Rootsoft-Algorand-KMD-Model-VersionsResponse.html │ ├── Rootsoft-Algorand-KMD-Model-WalletInfoRequest.html │ ├── Rootsoft-Algorand-KMD-ObjectSerializer.html │ ├── Rootsoft-Algorand-Managers-AccountManager.html │ ├── Rootsoft-Algorand-Managers-ApplicationManager.html │ ├── Rootsoft-Algorand-Managers-AssetManager.html │ ├── Rootsoft-Algorand-Mnemonic-Mnemonic.html │ ├── Rootsoft-Algorand-Mnemonic-SeedPhrase.html │ ├── Rootsoft-Algorand-Mnemonic-WordList.html │ ├── Rootsoft-Algorand-Models-AccountParticipation.html │ ├── Rootsoft-Algorand-Models-Accounts-Account.html │ ├── Rootsoft-Algorand-Models-Accounts-AccountInformation.html │ ├── Rootsoft-Algorand-Models-Accounts-Address.html │ ├── Rootsoft-Algorand-Models-Accounts-SearchAccountsResult.html │ ├── Rootsoft-Algorand-Models-Addresses-AddressRole.html │ ├── Rootsoft-Algorand-Models-Allocation.html │ ├── Rootsoft-Algorand-Models-AllocationState.html │ ├── Rootsoft-Algorand-Models-Application.html │ ├── Rootsoft-Algorand-Models-ApplicationLocalState.html │ ├── Rootsoft-Algorand-Models-ApplicationParams.html │ ├── Rootsoft-Algorand-Models-ApplicationStateSchema.html │ ├── Rootsoft-Algorand-Models-Applications-OnCompletion.html │ ├── Rootsoft-Algorand-Models-Applications-SearchApplicationsResult.html │ ├── Rootsoft-Algorand-Models-Applications-StateSchema.html │ ├── Rootsoft-Algorand-Models-Applications-TEALProgram.html │ ├── Rootsoft-Algorand-Models-AssetHolding.html │ ├── Rootsoft-Algorand-Models-Assets-Asset.html │ ├── Rootsoft-Algorand-Models-Assets-AssetParams.html │ ├── Rootsoft-Algorand-Models-Assets-AssetResult.html │ ├── Rootsoft-Algorand-Models-Assets-SearchAssetsResult.html │ ├── Rootsoft-Algorand-Models-Blocks-Block.html │ ├── Rootsoft-Algorand-Models-Blocks-BlockResult.html │ ├── Rootsoft-Algorand-Models-Catchups-CatchupResult.html │ ├── Rootsoft-Algorand-Models-GenesisInformation.html │ ├── Rootsoft-Algorand-Models-Indexer-IndexerHealth.html │ ├── Rootsoft-Algorand-Models-Keys-ParticipationPublicKey.html │ ├── Rootsoft-Algorand-Models-Keys-VRFPublicKey.html │ ├── Rootsoft-Algorand-Models-Ledgers-LedgerSupplyResult.html │ ├── Rootsoft-Algorand-Models-MiniAssetHolding.html │ ├── Rootsoft-Algorand-Models-NodeStatus.html │ ├── Rootsoft-Algorand-Models-PendingTransactionsResult.html │ ├── Rootsoft-Algorand-Models-SignatureType.html │ ├── Rootsoft-Algorand-Models-TealKeyValueStore.html │ ├── Rootsoft-Algorand-Models-TealValue.html │ ├── Rootsoft-Algorand-Models-Teals-DryrunRequest.html │ ├── Rootsoft-Algorand-Models-Teals-DryrunResponse.html │ ├── Rootsoft-Algorand-Models-Teals-DryrunSource.html │ ├── Rootsoft-Algorand-Models-Teals-TealCompilationResult.html │ ├── Rootsoft-Algorand-Models-Transactions-AssetConfigTransactionResult.html │ ├── Rootsoft-Algorand-Models-Transactions-AssetTransferTransactionResult.html │ ├── Rootsoft-Algorand-Models-Transactions-AtomicTransfer.html │ ├── Rootsoft-Algorand-Models-Transactions-Builders-ApplicationBaseTransactionBuilder.html │ ├── Rootsoft-Algorand-Models-Transactions-Builders-ApplicationCreateTransactionBuilder.html │ ├── Rootsoft-Algorand-Models-Transactions-Builders-ApplicationUpdateTransactionBuilder.html │ ├── Rootsoft-Algorand-Models-Transactions-Builders-AssetConfigTransactionBuilder.html │ ├── Rootsoft-Algorand-Models-Transactions-Builders-AssetFreezeTransactionBuilder.html │ ├── Rootsoft-Algorand-Models-Transactions-Builders-AssetTransferTransactionBuilder.html │ ├── Rootsoft-Algorand-Models-Transactions-Builders-KeyRegistrationTransactionBuilder.html │ ├── Rootsoft-Algorand-Models-Transactions-Builders-PaymentTransactionBuilder.html │ ├── Rootsoft-Algorand-Models-Transactions-Builders-RawTransactionBuilder.html │ ├── Rootsoft-Algorand-Models-Transactions-Builders-TransactionBuilder.html │ ├── Rootsoft-Algorand-Models-Transactions-PaymentTransaction.html │ ├── Rootsoft-Algorand-Models-Transactions-PendingTransaction.html │ ├── Rootsoft-Algorand-Models-Transactions-RawTransaction.html │ ├── Rootsoft-Algorand-Models-Transactions-SearchTransactionsResult.html │ ├── Rootsoft-Algorand-Models-Transactions-SignedTransaction.html │ ├── Rootsoft-Algorand-Models-Transactions-Transaction.html │ ├── Rootsoft-Algorand-Models-Transactions-TransactionParams.html │ ├── Rootsoft-Algorand-Models-Transactions-TransactionResult.html │ ├── Rootsoft-Algorand-Models-Transactions-TransactionSignature.html │ ├── Rootsoft-Algorand-Models-Transactions-TransactionType.html │ ├── Rootsoft-Algorand-Models-Transactions-Types-ApplicationBaseTransaction.html │ ├── Rootsoft-Algorand-Models-Transactions-Types-ApplicationCreateTransaction.html │ ├── Rootsoft-Algorand-Models-Transactions-Types-ApplicationUpdateTransaction.html │ ├── Rootsoft-Algorand-Models-Transactions-Types-AssetConfigTransaction.html │ ├── Rootsoft-Algorand-Models-Transactions-Types-AssetFreezeTransaction.html │ ├── Rootsoft-Algorand-Models-Transactions-Types-AssetTransferTransaction.html │ ├── Rootsoft-Algorand-Models-Transactions-Types-KeyRegistrationTransaction.html │ ├── Rootsoft-Algorand-Models-Transactions-Types-RawPaymentTransaction.html │ ├── Rootsoft-Algorand-Services-ManagesAccountsV2.html │ ├── Rootsoft-Algorand-Services-ManagesApplicationsV2.html │ ├── Rootsoft-Algorand-Services-ManagesAssetsV2.html │ ├── Rootsoft-Algorand-Services-ManagesBalanceV2.html │ ├── Rootsoft-Algorand-Services-ManagesBlocksV2.html │ ├── Rootsoft-Algorand-Services-ManagesCatchupsV2.html │ ├── Rootsoft-Algorand-Services-ManagesLedgerV2.html │ ├── Rootsoft-Algorand-Services-ManagesNodesV2.html │ ├── Rootsoft-Algorand-Services-ManagesParticipationV2.html │ ├── Rootsoft-Algorand-Services-ManagesTransactionParamsV2.html │ ├── Rootsoft-Algorand-Services-ManagesTransactionsV2.html │ ├── Rootsoft-Algorand-Templates-ContractTemplate.html │ ├── Rootsoft-Algorand-Templates-DynamicFee.html │ ├── Rootsoft-Algorand-Templates-HashTimeLockContract.html │ ├── Rootsoft-Algorand-Templates-LimitOrder.html │ ├── Rootsoft-Algorand-Templates-Parameters-AddressParameterValue.html │ ├── Rootsoft-Algorand-Templates-Parameters-BytesParameterValue.html │ ├── Rootsoft-Algorand-Templates-Parameters-IntParameterValue.html │ ├── Rootsoft-Algorand-Templates-Parameters-ParameterValue.html │ ├── Rootsoft-Algorand-Templates-PeriodicPayment.html │ ├── Rootsoft-Algorand-Templates-Split.html │ ├── Rootsoft-Algorand-Traits-KeyPairGenerator.html │ ├── Rootsoft-Algorand-Traits-MakesHttpRequests.html │ ├── Rootsoft-Algorand-Utils-Algo.html │ ├── Rootsoft-Algorand-Utils-AlgorandUtils.html │ ├── Rootsoft-Algorand-Utils-ArrayUtils.html │ ├── Rootsoft-Algorand-Utils-BigIntTransformer.html │ ├── Rootsoft-Algorand-Utils-Buffer.html │ ├── Rootsoft-Algorand-Utils-CryptoUtils.html │ ├── Rootsoft-Algorand-Utils-Encoder-EncoderUtils.html │ ├── Rootsoft-Algorand-Utils-Encoder.html │ ├── Rootsoft-Algorand-Utils-FeeCalculator.html │ ├── Rootsoft-Algorand-Utils-MessagePackable.html │ ├── Rootsoft-Algorand-Utils-Transformers-ApplicationCreateTransformer.html │ ├── Rootsoft-Algorand-Utils-Transformers-ApplicationTransformer.html │ ├── Rootsoft-Algorand-Utils-Transformers-ApplicationUpdateTransformer.html │ ├── Rootsoft-Algorand-Utils-Transformers-AssetConfigTransformer.html │ ├── Rootsoft-Algorand-Utils-Transformers-AssetFreezeTransformer.html │ ├── Rootsoft-Algorand-Utils-Transformers-AssetTransferTransformer.html │ ├── Rootsoft-Algorand-Utils-Transformers-BaseTransactionTransformer.html │ ├── Rootsoft-Algorand-Utils-Transformers-KeyRegistrationTransformer.html │ ├── Rootsoft-Algorand-Utils-Transformers-LogicSignatureTransformer.html │ ├── Rootsoft-Algorand-Utils-Transformers-MessagePackTransformer.html │ ├── Rootsoft-Algorand-Utils-Transformers-PaymentTransactionTransformer.html │ ├── Rootsoft-Algorand-Utils-Transformers-SignedTransactionTransformer.html │ └── Rootsoft-Algorand-Utils-Transformers-TransformerFactory.html │ ├── css │ ├── base.css │ ├── normalize.css │ └── template.css │ ├── files │ ├── algorand-php-src-algorand.html │ ├── algorand-php-src-algorandserviceprovider.html │ ├── algorand-php-src-clients-algodclient.html │ ├── algorand-php-src-clients-algoexplorer.html │ ├── algorand-php-src-clients-algorandclient.html │ ├── algorand-php-src-clients-indexerclient.html │ ├── algorand-php-src-clients-kmdclient.html │ ├── algorand-php-src-clients-purestake.html │ ├── algorand-php-src-config-algorand.html │ ├── algorand-php-src-crypto-ed25519publickey.html │ ├── algorand-php-src-crypto-logic.html │ ├── algorand-php-src-crypto-logicsignature.html │ ├── algorand-php-src-crypto-multisignature.html │ ├── algorand-php-src-crypto-multisignatureaddress.html │ ├── algorand-php-src-crypto-multisigsubsig.html │ ├── algorand-php-src-crypto-signature.html │ ├── algorand-php-src-exceptions-algorandexception.html │ ├── algorand-php-src-exceptions-apikeyexception.html │ ├── algorand-php-src-exceptions-invalidrequestexception.html │ ├── algorand-php-src-exceptions-mnemonicexception.html │ ├── algorand-php-src-exceptions-notfoundexception.html │ ├── algorand-php-src-exceptions-notimplementedexception.html │ ├── algorand-php-src-exceptions-overquerylimitexception.html │ ├── algorand-php-src-exceptions-overspendexception.html │ ├── algorand-php-src-exceptions-requestdeniedexception.html │ ├── algorand-php-src-exceptions-wordlistexception.html │ ├── algorand-php-src-facades-algorandfacade.html │ ├── algorand-php-src-indexer-algorandindexer.html │ ├── algorand-php-src-indexer-builders-accountquerybuilder.html │ ├── algorand-php-src-indexer-builders-applicationquerybuilder.html │ ├── algorand-php-src-indexer-builders-assetquerybuilder.html │ ├── algorand-php-src-indexer-builders-transactionquerybuilder.html │ ├── algorand-php-src-indexer-querybuilder.html │ ├── algorand-php-src-indexer-services-managesindexeraccountsv2.html │ ├── algorand-php-src-indexer-services-managesindexerapplicationsv2.html │ ├── algorand-php-src-indexer-services-managesindexerassetsv2.html │ ├── algorand-php-src-indexer-services-managesindexertransactionsv2.html │ ├── algorand-php-src-indexer-services-managesindexerv2.html │ ├── algorand-php-src-kmd-api-kmdapi.html │ ├── algorand-php-src-kmd-apiexception.html │ ├── algorand-php-src-kmd-configuration.html │ ├── algorand-php-src-kmd-headerselector.html │ ├── algorand-php-src-kmd-model-apiv1deletekeyresponse.html │ ├── algorand-php-src-kmd-model-apiv1deletemultisigresponse.html │ ├── algorand-php-src-kmd-model-apiv1getwalletsresponse.html │ ├── algorand-php-src-kmd-model-apiv1postkeyexportresponse.html │ ├── algorand-php-src-kmd-model-apiv1postkeyimportresponse.html │ ├── algorand-php-src-kmd-model-apiv1postkeylistresponse.html │ ├── algorand-php-src-kmd-model-apiv1postkeyresponse.html │ ├── algorand-php-src-kmd-model-apiv1postmasterkeyexportresponse.html │ ├── algorand-php-src-kmd-model-apiv1postmultisigexportresponse.html │ ├── algorand-php-src-kmd-model-apiv1postmultisigimportresponse.html │ ├── algorand-php-src-kmd-model-apiv1postmultisiglistresponse.html │ ├── algorand-php-src-kmd-model-apiv1postmultisigprogramsignresponse.html │ ├── algorand-php-src-kmd-model-apiv1postmultisigtransactionsignresponse.html │ ├── algorand-php-src-kmd-model-apiv1postprogramsignresponse.html │ ├── algorand-php-src-kmd-model-apiv1posttransactionsignresponse.html │ ├── algorand-php-src-kmd-model-apiv1postwalletinforesponse.html │ ├── algorand-php-src-kmd-model-apiv1postwalletinitresponse.html │ ├── algorand-php-src-kmd-model-apiv1postwalletreleaseresponse.html │ ├── algorand-php-src-kmd-model-apiv1postwalletrenameresponse.html │ ├── algorand-php-src-kmd-model-apiv1postwalletrenewresponse.html │ ├── algorand-php-src-kmd-model-apiv1postwalletresponse.html │ ├── algorand-php-src-kmd-model-apiv1wallet.html │ ├── algorand-php-src-kmd-model-apiv1wallethandle.html │ ├── algorand-php-src-kmd-model-createwalletrequest.html │ ├── algorand-php-src-kmd-model-deletekeyrequest.html │ ├── algorand-php-src-kmd-model-deletemultisigrequest.html │ ├── algorand-php-src-kmd-model-exportkeyrequest.html │ ├── algorand-php-src-kmd-model-exportmasterkeyrequest.html │ ├── algorand-php-src-kmd-model-exportmultisigrequest.html │ ├── algorand-php-src-kmd-model-generatekeyrequest.html │ ├── algorand-php-src-kmd-model-importkeyrequest.html │ ├── algorand-php-src-kmd-model-importmultisigrequest.html │ ├── algorand-php-src-kmd-model-initwallethandletokenrequest.html │ ├── algorand-php-src-kmd-model-listkeysrequest.html │ ├── algorand-php-src-kmd-model-listmultisigrequest.html │ ├── algorand-php-src-kmd-model-modelinterface.html │ ├── algorand-php-src-kmd-model-multisigsig.html │ ├── algorand-php-src-kmd-model-multisigsubsig.html │ ├── algorand-php-src-kmd-model-releasewallethandletokenrequest.html │ ├── algorand-php-src-kmd-model-renamewalletrequest.html │ ├── algorand-php-src-kmd-model-renewwallethandletokenrequest.html │ ├── algorand-php-src-kmd-model-signmultisigrequest.html │ ├── algorand-php-src-kmd-model-signprogrammultisigrequest.html │ ├── algorand-php-src-kmd-model-signprogramrequest.html │ ├── algorand-php-src-kmd-model-signtransactionrequest.html │ ├── algorand-php-src-kmd-model-versionsresponse.html │ ├── algorand-php-src-kmd-model-walletinforequest.html │ ├── algorand-php-src-kmd-objectserializer.html │ ├── algorand-php-src-managers-accountmanager.html │ ├── algorand-php-src-managers-applicationmanager.html │ ├── algorand-php-src-managers-assetmanager.html │ ├── algorand-php-src-mnemonic-mnemonic.html │ ├── algorand-php-src-mnemonic-seedphrase.html │ ├── algorand-php-src-mnemonic-wordlist.html │ ├── algorand-php-src-models-accountparticipation.html │ ├── algorand-php-src-models-accounts-account.html │ ├── algorand-php-src-models-accounts-accountinformation.html │ ├── algorand-php-src-models-accounts-address.html │ ├── algorand-php-src-models-accounts-searchaccountsresult.html │ ├── algorand-php-src-models-addresses-addressrole.html │ ├── algorand-php-src-models-allocation.html │ ├── algorand-php-src-models-allocationstate.html │ ├── algorand-php-src-models-application.html │ ├── algorand-php-src-models-applicationlocalstate.html │ ├── algorand-php-src-models-applicationparams.html │ ├── algorand-php-src-models-applications-oncompletion.html │ ├── algorand-php-src-models-applications-searchapplicationsresult.html │ ├── algorand-php-src-models-applications-stateschema.html │ ├── algorand-php-src-models-applications-tealprogram.html │ ├── algorand-php-src-models-applicationstateschema.html │ ├── algorand-php-src-models-assetholding.html │ ├── algorand-php-src-models-assets-asset.html │ ├── algorand-php-src-models-assets-assetparams.html │ ├── algorand-php-src-models-assets-assetresult.html │ ├── algorand-php-src-models-assets-searchassetsresult.html │ ├── algorand-php-src-models-blocks-block.html │ ├── algorand-php-src-models-blocks-blockresult.html │ ├── algorand-php-src-models-catchups-catchupresult.html │ ├── algorand-php-src-models-genesisinformation.html │ ├── algorand-php-src-models-indexer-indexerhealth.html │ ├── algorand-php-src-models-keys-participationpublickey.html │ ├── algorand-php-src-models-keys-vrfpublickey.html │ ├── algorand-php-src-models-ledgers-ledgersupplyresult.html │ ├── algorand-php-src-models-miniassetholding.html │ ├── algorand-php-src-models-nodestatus.html │ ├── algorand-php-src-models-pendingtransactionsresult.html │ ├── algorand-php-src-models-signaturetype.html │ ├── algorand-php-src-models-tealkeyvaluestore.html │ ├── algorand-php-src-models-teals-dryrunrequest.html │ ├── algorand-php-src-models-teals-dryrunresponse.html │ ├── algorand-php-src-models-teals-dryrunsource.html │ ├── algorand-php-src-models-teals-tealcompilationresult.html │ ├── algorand-php-src-models-tealvalue.html │ ├── algorand-php-src-models-transactions-assetconfigtransactionresult.html │ ├── algorand-php-src-models-transactions-assettransfertransactionresult.html │ ├── algorand-php-src-models-transactions-atomictransfer.html │ ├── algorand-php-src-models-transactions-builders-applicationbasetransactionbuilder.html │ ├── algorand-php-src-models-transactions-builders-applicationcreatetransactionbuilder.html │ ├── algorand-php-src-models-transactions-builders-applicationupdatetransactionbuilder.html │ ├── algorand-php-src-models-transactions-builders-assetconfigtransactionbuilder.html │ ├── algorand-php-src-models-transactions-builders-assetfreezetransactionbuilder.html │ ├── algorand-php-src-models-transactions-builders-assettransfertransactionbuilder.html │ ├── algorand-php-src-models-transactions-builders-keyregistrationtransactionbuilder.html │ ├── algorand-php-src-models-transactions-builders-paymenttransactionbuilder.html │ ├── algorand-php-src-models-transactions-builders-rawtransactionbuilder.html │ ├── algorand-php-src-models-transactions-builders-transactionbuilder.html │ ├── algorand-php-src-models-transactions-paymenttransaction.html │ ├── algorand-php-src-models-transactions-pendingtransaction.html │ ├── algorand-php-src-models-transactions-rawtransaction.html │ ├── algorand-php-src-models-transactions-searchtransactionsresult.html │ ├── algorand-php-src-models-transactions-signedtransaction.html │ ├── algorand-php-src-models-transactions-transaction.html │ ├── algorand-php-src-models-transactions-transactionparams.html │ ├── algorand-php-src-models-transactions-transactionresult.html │ ├── algorand-php-src-models-transactions-transactionsignature.html │ ├── algorand-php-src-models-transactions-transactiontype.html │ ├── algorand-php-src-models-transactions-types-applicationbasetransaction.html │ ├── algorand-php-src-models-transactions-types-applicationcreatetransaction.html │ ├── algorand-php-src-models-transactions-types-applicationupdatetransaction.html │ ├── algorand-php-src-models-transactions-types-assetconfigtransaction.html │ ├── algorand-php-src-models-transactions-types-assetfreezetransaction.html │ ├── algorand-php-src-models-transactions-types-assettransfertransaction.html │ ├── algorand-php-src-models-transactions-types-keyregistrationtransaction.html │ ├── algorand-php-src-models-transactions-types-rawpaymenttransaction.html │ ├── algorand-php-src-services-managesaccountsv2.html │ ├── algorand-php-src-services-managesapplicationsv2.html │ ├── algorand-php-src-services-managesassetsv2.html │ ├── algorand-php-src-services-managesbalancev2.html │ ├── algorand-php-src-services-managesblocksv2.html │ ├── algorand-php-src-services-managescatchupsv2.html │ ├── algorand-php-src-services-managesledgerv2.html │ ├── algorand-php-src-services-managesnodesv2.html │ ├── algorand-php-src-services-managesparticipationv2.html │ ├── algorand-php-src-services-managestransactionparamsv2.html │ ├── algorand-php-src-services-managestransactionsv2.html │ ├── algorand-php-src-templates-contracttemplate.html │ ├── algorand-php-src-templates-dynamicfee.html │ ├── algorand-php-src-templates-hashtimelockcontract.html │ ├── algorand-php-src-templates-limitorder.html │ ├── algorand-php-src-templates-parameters-addressparametervalue.html │ ├── algorand-php-src-templates-parameters-bytesparametervalue.html │ ├── algorand-php-src-templates-parameters-intparametervalue.html │ ├── algorand-php-src-templates-parameters-parametervalue.html │ ├── algorand-php-src-templates-periodicpayment.html │ ├── algorand-php-src-templates-split.html │ ├── algorand-php-src-traits-keypairgenerator.html │ ├── algorand-php-src-traits-makeshttprequests.html │ ├── algorand-php-src-utils-algo.html │ ├── algorand-php-src-utils-algorandutils.html │ ├── algorand-php-src-utils-arrayutils.html │ ├── algorand-php-src-utils-biginttransformer.html │ ├── algorand-php-src-utils-buffer.html │ ├── algorand-php-src-utils-cryptoutils.html │ ├── algorand-php-src-utils-encoder-encoderutils.html │ ├── algorand-php-src-utils-encoder.html │ ├── algorand-php-src-utils-feecalculator.html │ ├── algorand-php-src-utils-messagepackable.html │ ├── algorand-php-src-utils-transformers-applicationcreatetransformer.html │ ├── algorand-php-src-utils-transformers-applicationtransformer.html │ ├── algorand-php-src-utils-transformers-applicationupdatetransformer.html │ ├── algorand-php-src-utils-transformers-assetconfigtransformer.html │ ├── algorand-php-src-utils-transformers-assetfreezetransformer.html │ ├── algorand-php-src-utils-transformers-assettransfertransformer.html │ ├── algorand-php-src-utils-transformers-basetransactiontransformer.html │ ├── algorand-php-src-utils-transformers-keyregistrationtransformer.html │ ├── algorand-php-src-utils-transformers-logicsignaturetransformer.html │ ├── algorand-php-src-utils-transformers-messagepacktransformer.html │ ├── algorand-php-src-utils-transformers-paymenttransactiontransformer.html │ ├── algorand-php-src-utils-transformers-signedtransactiontransformer.html │ └── algorand-php-src-utils-transformers-transformerfactory.html │ ├── graphs │ └── classes.html │ ├── index.html │ ├── indices │ └── files.html │ ├── js │ ├── search.js │ └── searchIndex.js │ ├── namespaces │ ├── default.html │ ├── rootsoft-algorand-clients.html │ ├── rootsoft-algorand-crypto.html │ ├── rootsoft-algorand-exceptions.html │ ├── rootsoft-algorand-facades.html │ ├── rootsoft-algorand-indexer-builders.html │ ├── rootsoft-algorand-indexer-services.html │ ├── rootsoft-algorand-indexer.html │ ├── rootsoft-algorand-kmd-api.html │ ├── rootsoft-algorand-kmd-model.html │ ├── rootsoft-algorand-kmd.html │ ├── rootsoft-algorand-managers.html │ ├── rootsoft-algorand-mnemonic.html │ ├── rootsoft-algorand-models-accounts.html │ ├── rootsoft-algorand-models-addresses.html │ ├── rootsoft-algorand-models-applications.html │ ├── rootsoft-algorand-models-assets.html │ ├── rootsoft-algorand-models-blocks.html │ ├── rootsoft-algorand-models-catchups.html │ ├── rootsoft-algorand-models-indexer.html │ ├── rootsoft-algorand-models-keys.html │ ├── rootsoft-algorand-models-ledgers.html │ ├── rootsoft-algorand-models-teals.html │ ├── rootsoft-algorand-models-transactions-builders.html │ ├── rootsoft-algorand-models-transactions-types.html │ ├── rootsoft-algorand-models-transactions.html │ ├── rootsoft-algorand-models.html │ ├── rootsoft-algorand-services.html │ ├── rootsoft-algorand-templates-parameters.html │ ├── rootsoft-algorand-templates.html │ ├── rootsoft-algorand-traits.html │ ├── rootsoft-algorand-utils-encoder.html │ ├── rootsoft-algorand-utils-transformers.html │ ├── rootsoft-algorand-utils.html │ ├── rootsoft-algorand.html │ └── rootsoft.html │ ├── packages │ ├── Application.html │ └── default.html │ └── reports │ ├── deprecated.html │ ├── errors.html │ └── markers.html ├── examples ├── accounts │ ├── AccountInformation.php │ └── CreateAccounts.php ├── assets │ └── AssetsExample.php ├── atomic-transfers │ └── AtomicTransferExample.php ├── avm │ ├── innertxns │ │ ├── InnerTxnsExample.php │ │ ├── approval.teal │ │ └── clear.teal │ ├── logs │ │ ├── LogExample.php │ │ ├── approval.teal │ │ └── clear.teal │ └── op-pool │ │ ├── OpPoolExample.php │ │ ├── approval.teal │ │ └── clear.teal ├── indexer │ └── IndexerExample.php ├── kmd │ └── KmdExample.php ├── multisig │ └── MultiSigExample.php ├── offline │ └── OfflineTransactionExample.php ├── smart-contracts │ ├── AccountDelegationExample.php │ ├── CompileTEALExample.php │ ├── ContractAccountExample.php │ └── StatefulSmartContractsExample.php └── start-building │ └── YourFirstTransactionExample.php ├── phpunit.xml ├── psalm.xml.dist ├── src ├── Algorand.php ├── AlgorandServiceProvider.php ├── Clients │ ├── AlgoExplorer.php │ ├── AlgodClient.php │ ├── AlgorandClient.php │ ├── IndexerClient.php │ ├── KmdClient.php │ └── PureStake.php ├── Crypto │ ├── Ed25519PublicKey.php │ ├── Logic.php │ ├── LogicSignature.php │ ├── MultiSignature.php │ ├── MultiSignatureAddress.php │ ├── MultisigSubsig.php │ ├── Signature.php │ └── langspec.json ├── Exceptions │ ├── AlgorandException.php │ ├── ApiKeyException.php │ ├── InvalidRequestException.php │ ├── MnemonicException.php │ ├── NotFoundException.php │ ├── NotImplementedException.php │ ├── OverQueryLimitException.php │ ├── OverspendException.php │ ├── RequestDeniedException.php │ └── WordListException.php ├── Facades │ └── AlgorandFacade.php ├── Indexer │ ├── AlgorandIndexer.php │ ├── Builders │ │ ├── AccountQueryBuilder.php │ │ ├── ApplicationQueryBuilder.php │ │ ├── AssetQueryBuilder.php │ │ └── TransactionQueryBuilder.php │ ├── QueryBuilder.php │ └── Services │ │ ├── ManagesIndexerAccountsV2.php │ │ ├── ManagesIndexerApplicationsV2.php │ │ ├── ManagesIndexerAssetsV2.php │ │ ├── ManagesIndexerTransactionsV2.php │ │ └── ManagesIndexerV2.php ├── KMD │ ├── Api │ │ └── KmdApi.php │ ├── ApiException.php │ ├── Configuration.php │ ├── HeaderSelector.php │ ├── Model │ │ ├── APIV1DELETEKeyResponse.php │ │ ├── APIV1DELETEMultisigResponse.php │ │ ├── APIV1GETWalletsResponse.php │ │ ├── APIV1POSTKeyExportResponse.php │ │ ├── APIV1POSTKeyImportResponse.php │ │ ├── APIV1POSTKeyListResponse.php │ │ ├── APIV1POSTKeyResponse.php │ │ ├── APIV1POSTMasterKeyExportResponse.php │ │ ├── APIV1POSTMultisigExportResponse.php │ │ ├── APIV1POSTMultisigImportResponse.php │ │ ├── APIV1POSTMultisigListResponse.php │ │ ├── APIV1POSTMultisigProgramSignResponse.php │ │ ├── APIV1POSTMultisigTransactionSignResponse.php │ │ ├── APIV1POSTProgramSignResponse.php │ │ ├── APIV1POSTTransactionSignResponse.php │ │ ├── APIV1POSTWalletInfoResponse.php │ │ ├── APIV1POSTWalletInitResponse.php │ │ ├── APIV1POSTWalletReleaseResponse.php │ │ ├── APIV1POSTWalletRenameResponse.php │ │ ├── APIV1POSTWalletRenewResponse.php │ │ ├── APIV1POSTWalletResponse.php │ │ ├── APIV1Wallet.php │ │ ├── APIV1WalletHandle.php │ │ ├── CreateWalletRequest.php │ │ ├── DeleteKeyRequest.php │ │ ├── DeleteMultisigRequest.php │ │ ├── ExportKeyRequest.php │ │ ├── ExportMasterKeyRequest.php │ │ ├── ExportMultisigRequest.php │ │ ├── GenerateKeyRequest.php │ │ ├── ImportKeyRequest.php │ │ ├── ImportMultisigRequest.php │ │ ├── InitWalletHandleTokenRequest.php │ │ ├── ListKeysRequest.php │ │ ├── ListMultisigRequest.php │ │ ├── ModelInterface.php │ │ ├── MultisigSig.php │ │ ├── MultisigSubsig.php │ │ ├── ReleaseWalletHandleTokenRequest.php │ │ ├── RenameWalletRequest.php │ │ ├── RenewWalletHandleTokenRequest.php │ │ ├── SignMultisigRequest.php │ │ ├── SignProgramMultisigRequest.php │ │ ├── SignProgramRequest.php │ │ ├── SignTransactionRequest.php │ │ ├── VersionsResponse.php │ │ └── WalletInfoRequest.php │ └── ObjectSerializer.php ├── Managers │ ├── AccountManager.php │ ├── ApplicationManager.php │ └── AssetManager.php ├── Mnemonic │ ├── Mnemonic.php │ ├── SeedPhrase.php │ ├── WordList.php │ └── wordlists │ │ └── english.txt ├── Models │ ├── AccountParticipation.php │ ├── Accounts │ │ ├── Account.php │ │ ├── AccountInformation.php │ │ ├── Address.php │ │ └── SearchAccountsResult.php │ ├── Addresses │ │ └── AddressRole.php │ ├── Allocation.php │ ├── AllocationState.php │ ├── Application.php │ ├── ApplicationLocalState.php │ ├── ApplicationParams.php │ ├── ApplicationStateSchema.php │ ├── Applications │ │ ├── AccountStateDelta.php │ │ ├── ApplicationLogData.php │ │ ├── ApplicationLogsResult.php │ │ ├── ApplicationResult.php │ │ ├── EvalDelta.php │ │ ├── EvalDeltaKeyValue.php │ │ ├── OnCompletion.php │ │ ├── SearchApplicationsResult.php │ │ ├── StateSchema.php │ │ └── TEALProgram.php │ ├── AssetHolding.php │ ├── Assets │ │ ├── Asset.php │ │ ├── AssetParams.php │ │ ├── AssetResult.php │ │ └── SearchAssetsResult.php │ ├── Blocks │ │ ├── Block.php │ │ └── BlockResult.php │ ├── Catchups │ │ └── CatchupResult.php │ ├── GenesisInformation.php │ ├── Indexer │ │ └── IndexerHealth.php │ ├── Keys │ │ ├── ParticipationPublicKey.php │ │ └── VRFPublicKey.php │ ├── Ledgers │ │ └── LedgerSupplyResult.php │ ├── MiniAssetHolding.php │ ├── NodeStatus.php │ ├── PendingTransactionsResult.php │ ├── SignatureType.php │ ├── TealKeyValueStore.php │ ├── TealValue.php │ ├── Teals │ │ ├── DryrunRequest.php │ │ ├── DryrunResponse.php │ │ ├── DryrunSource.php │ │ └── TealCompilationResult.php │ └── Transactions │ │ ├── ApplicationTransactionResult.php │ │ ├── AssetConfigTransactionResult.php │ │ ├── AssetFreezeTransactionResult.php │ │ ├── AssetTransferTransactionResult.php │ │ ├── AtomicTransfer.php │ │ ├── Builders │ │ ├── ApplicationBaseTransactionBuilder.php │ │ ├── ApplicationCreateTransactionBuilder.php │ │ ├── ApplicationUpdateTransactionBuilder.php │ │ ├── AssetConfigTransactionBuilder.php │ │ ├── AssetFreezeTransactionBuilder.php │ │ ├── AssetTransferTransactionBuilder.php │ │ ├── KeyRegistrationTransactionBuilder.php │ │ ├── PaymentTransactionBuilder.php │ │ ├── RawTransactionBuilder.php │ │ └── TransactionBuilder.php │ │ ├── KeyRegistrationTransactionResponse.php │ │ ├── PaymentTransaction.php │ │ ├── PendingTransaction.php │ │ ├── RawTransaction.php │ │ ├── SearchTransactionsResult.php │ │ ├── SignedTransaction.php │ │ ├── Transaction.php │ │ ├── TransactionParams.php │ │ ├── TransactionResult.php │ │ ├── TransactionSignature.php │ │ ├── TransactionType.php │ │ └── Types │ │ ├── ApplicationBaseTransaction.php │ │ ├── ApplicationCreateTransaction.php │ │ ├── ApplicationUpdateTransaction.php │ │ ├── AssetConfigTransaction.php │ │ ├── AssetFreezeTransaction.php │ │ ├── AssetTransferTransaction.php │ │ ├── KeyRegistrationTransaction.php │ │ └── RawPaymentTransaction.php ├── Services │ ├── ManagesAccountsV2.php │ ├── ManagesApplicationsV2.php │ ├── ManagesAssetsV2.php │ ├── ManagesBalanceV2.php │ ├── ManagesBlocksV2.php │ ├── ManagesCatchupsV2.php │ ├── ManagesLedgerV2.php │ ├── ManagesNodesV2.php │ ├── ManagesParticipationV2.php │ ├── ManagesTransactionParamsV2.php │ └── ManagesTransactionsV2.php ├── Templates │ ├── ContractTemplate.php │ ├── DynamicFee.php │ ├── HashTimeLockContract.php │ ├── LimitOrder.php │ ├── Parameters │ │ ├── AddressParameterValue.php │ │ ├── BytesParameterValue.php │ │ ├── IntParameterValue.php │ │ └── ParameterValue.php │ ├── PeriodicPayment.php │ └── Split.php ├── Traits │ ├── KeyPairGenerator.php │ └── MakesHttpRequests.php ├── Utils │ ├── Algo.php │ ├── AlgorandUtils.php │ ├── ArrayUtils.php │ ├── BigIntTransformer.php │ ├── Buffer.php │ ├── CryptoUtils.php │ ├── Encoder.php │ ├── Encoder │ │ ├── BigIntEncoder.php │ │ └── EncoderUtils.php │ ├── FeeCalculator.php │ ├── MessagePackable.php │ └── Transformers │ │ ├── ApplicationCreateTransformer.php │ │ ├── ApplicationTransformer.php │ │ ├── ApplicationUpdateTransformer.php │ │ ├── AssetConfigTransformer.php │ │ ├── AssetFreezeTransformer.php │ │ ├── AssetTransferTransformer.php │ │ ├── BaseTransactionTransformer.php │ │ ├── KeyRegistrationTransformer.php │ │ ├── LogicSignatureTransformer.php │ │ ├── MessagePackTransformer.php │ │ ├── PaymentTransactionTransformer.php │ │ ├── SignedTransactionTransformer.php │ │ └── TransformerFactory.php └── config │ └── algorand.php └── tests ├── Feature └── AlgorandTest.php ├── TestCase.php └── Unit ├── Accounts └── AccountTest.php ├── Crypto ├── AddressTest.php ├── LogicSigTest.php └── MultiSigAddressTest.php ├── Encoder └── EncoderTest.php ├── Logic └── LogicTest.php ├── Mnemonic └── MnemonicTest.php ├── Teal └── TealSignTest.php ├── Templates ├── DynamicFeeTest.php ├── HashTimeLockContractTest.php ├── LimitOrderTest.php ├── PeriodicPaymentTest.php └── SplitTest.php └── Transactions └── TransactionsTest.php /.github/workflows/tests.yml: -------------------------------------------------------------------------------- 1 | name: PHP Composer 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | jobs: 10 | build: 11 | 12 | runs-on: ubuntu-latest 13 | 14 | steps: 15 | - uses: actions/checkout@v2 16 | 17 | - name: Validate composer.json and composer.lock 18 | run: composer validate --strict 19 | 20 | - name: Cache Composer packages 21 | id: composer-cache 22 | uses: actions/cache@v2 23 | with: 24 | path: vendor 25 | key: ${{ runner.os }}-php-${{ hashFiles('**/composer.lock') }} 26 | restore-keys: | 27 | ${{ runner.os }}-php- 28 | 29 | - name: Install dependencies 30 | run: composer install --prefer-dist --no-progress 31 | 32 | # Add a test script to composer.json, for instance: "test": "vendor/bin/phpunit" 33 | # Docs: https://getcomposer.org/doc/articles/scripts.md 34 | 35 | - name: Run test suite 36 | run: composer run-script test 37 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## 0.0.7 - 2022-02-10 4 | 5 | - Support for TEAL 5 & AVM 1 6 | - Utility methods 7 | - Updated dependencies 8 | - Added AVM examples 9 | - Bugfixes and code cleanup 10 | 11 | ## 0.0.6 - 2021-09-13 12 | 13 | - Added support for KMD 14 | - Bugfixes and code cleanup 15 | 16 | ## 0.0.5 - 2021-09-12 17 | 18 | - Added Smart Contract Templates 19 | - Added MessagePack decoding 20 | - Added examples 21 | - Added tests 22 | 23 | ## 0.0.4 - 2021-08-14 24 | 25 | - Support for Logic Signatures (contract, account, account delegation, ..) 26 | - Support for Stateful smart contracts 27 | - MultiSignatures and msig addresses 28 | - Search applications with indexer 29 | - Sign TEAL programs 30 | - dryrun requests 31 | - Rekeying 32 | - Added support for key registration transaction 33 | - Small bugfixes 34 | 35 | ## 0.0.1 - 2021-02-27 36 | 37 | - initial beta release 38 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) RootSoft 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rootsoft/algorand-php", 3 | "description": "Community SDK to interact with the Algorand network, in PHP & Laravel", 4 | "keywords": [ 5 | "rootsoft", 6 | "algorand-php", 7 | "algorand", 8 | "blockchain" 9 | ], 10 | "homepage": "https://github.com/rootsoft/algorand-php", 11 | "license": "MIT", 12 | "authors": [ 13 | { 14 | "name": "Tomas Verhelst", 15 | "email": "tomasverhelst@gmail.com", 16 | "role": "Developer" 17 | } 18 | ], 19 | "require": { 20 | "php": "^7.4|^8.0", 21 | "ext-json": "*", 22 | "brick/math": "^0.9.3", 23 | "guzzlehttp/guzzle": "^7.4.1", 24 | "guzzlehttp/psr7": "^1.8.2|^2.1.0", 25 | "illuminate/container": "^6.0|^7.0|^8.0|^9.0", 26 | "illuminate/support": "^6.0|^7.0|^8.0|^9.0", 27 | "json-mapper/json-mapper": "^2.12.0", 28 | "myclabs/php-enum": "^1.7", 29 | "paragonie/constant_time_encoding": "^2.4", 30 | "paragonie/halite": "^5.0.0", 31 | "rybakit/msgpack": "^0.7.2" 32 | }, 33 | "require-dev": { 34 | "friendsofphp/php-cs-fixer": "^3.1", 35 | "orchestra/testbench": "^6.12", 36 | "phpunit/phpunit": "^9.5", 37 | "spatie/ray": "^1.10" 38 | }, 39 | "autoload": { 40 | "psr-4": { 41 | "Rootsoft\\Algorand\\": "src" 42 | } 43 | }, 44 | "autoload-dev": { 45 | "psr-4": { 46 | "Rootsoft\\Algorand\\Tests\\": "tests" 47 | } 48 | }, 49 | "extra": { 50 | "laravel": { 51 | "providers": [ 52 | "Rootsoft\\Algorand\\AlgorandServiceProvider" 53 | ], 54 | "aliases": { 55 | "Algorand": "Rootsoft\\Algorand\\Facades\\AlgorandFacade" 56 | } 57 | } 58 | }, 59 | "scripts": { 60 | "psalm": "vendor/bin/psalm", 61 | "test": "vendor/bin/phpunit", 62 | "test-coverage": "vendor/bin/phpunit --coverage-html coverage", 63 | "format": "vendor/bin/php-cs-fixer fix --allow-risky=yes" 64 | }, 65 | "config": { 66 | "sort-packages": true 67 | }, 68 | "minimum-stability": "dev", 69 | "prefer-stable": true 70 | } 71 | -------------------------------------------------------------------------------- /examples/accounts/AccountInformation.php: -------------------------------------------------------------------------------- 1 | indexer()->getCreatedAssets($address->encodedAddress); 29 | return $assets->assets; 30 | } 31 | } 32 | 33 | AccountInformation::main(); 34 | 35 | function prettyPrint($data) 36 | { 37 | echo $data . PHP_EOL; 38 | } 39 | -------------------------------------------------------------------------------- /examples/accounts/CreateAccounts.php: -------------------------------------------------------------------------------- 1 | getPublicAddress()); 13 | prettyPrint('My passphrase 1: ' . implode(' ', $account->getSeedPhrase()->words)); 14 | 15 | $account = Account::random(); 16 | prettyPrint('My address 2: ' . $account->getPublicAddress()); 17 | prettyPrint('My passphrase 2: ' . implode(' ', $account->getSeedPhrase()->words)); 18 | 19 | $account = Account::random(); 20 | prettyPrint('My address 3: ' . $account->getPublicAddress()); 21 | prettyPrint('My passphrase 3: ' . implode(' ', $account->getSeedPhrase()->words)); 22 | } 23 | } 24 | 25 | CreateAccounts::main(); 26 | 27 | function prettyPrint($data) 28 | { 29 | echo $data . PHP_EOL; 30 | } 31 | -------------------------------------------------------------------------------- /examples/avm/innertxns/approval.teal: -------------------------------------------------------------------------------- 1 | #pragma version 5 2 | txn ApplicationID 3 | int 0 4 | == 5 | bnz main_l12 6 | txn OnCompletion 7 | int DeleteApplication 8 | == 9 | bnz main_l11 10 | txn OnCompletion 11 | int UpdateApplication 12 | == 13 | bnz main_l10 14 | txn OnCompletion 15 | int CloseOut 16 | == 17 | bnz main_l9 18 | txn OnCompletion 19 | int OptIn 20 | == 21 | bnz main_l8 22 | txn OnCompletion 23 | int NoOp 24 | == 25 | bnz main_l7 26 | err 27 | main_l7: 28 | txn Sender 29 | global CreatorAddress 30 | == 31 | itxn_begin 32 | int acfg 33 | itxn_field TypeEnum 34 | txna ApplicationArgs 0 35 | itxn_field ConfigAssetName 36 | txna ApplicationArgs 1 37 | itxn_field ConfigAssetUnitName 38 | global CurrentApplicationAddress 39 | itxn_field ConfigAssetManager 40 | global CurrentApplicationAddress 41 | itxn_field ConfigAssetClawback 42 | global CurrentApplicationAddress 43 | itxn_field ConfigAssetReserve 44 | global CurrentApplicationAddress 45 | itxn_field ConfigAssetFreeze 46 | txna ApplicationArgs 2 47 | btoi 48 | itxn_field ConfigAssetTotal 49 | int 0 50 | itxn_field ConfigAssetDecimals 51 | itxn_submit 52 | int 1 53 | && 54 | return 55 | main_l8: 56 | int 1 57 | return 58 | main_l9: 59 | int 1 60 | return 61 | main_l10: 62 | txn Sender 63 | global CreatorAddress 64 | == 65 | return 66 | main_l11: 67 | txn Sender 68 | global CreatorAddress 69 | == 70 | return 71 | main_l12: 72 | int 1 73 | return -------------------------------------------------------------------------------- /examples/avm/innertxns/clear.teal: -------------------------------------------------------------------------------- 1 | #pragma version 5 2 | int 1 3 | return -------------------------------------------------------------------------------- /examples/avm/logs/approval.teal: -------------------------------------------------------------------------------- 1 | #pragma version 5 2 | txn ApplicationID 3 | int 0 4 | == 5 | bnz main_l15 6 | txn OnCompletion 7 | int DeleteApplication 8 | == 9 | bnz main_l14 10 | txn OnCompletion 11 | int UpdateApplication 12 | == 13 | bnz main_l13 14 | txn OnCompletion 15 | int CloseOut 16 | == 17 | bnz main_l12 18 | txn OnCompletion 19 | int OptIn 20 | == 21 | bnz main_l11 22 | txn OnCompletion 23 | int NoOp 24 | == 25 | bnz main_l7 26 | err 27 | main_l7: 28 | int 99 29 | store 0 30 | main_l8: 31 | load 0 32 | int 97 33 | > 34 | bnz main_l10 35 | int 1 36 | return 37 | main_l10: 38 | load 0 39 | callsub sub2 40 | load 0 41 | int 1 42 | - 43 | store 0 44 | b main_l8 45 | main_l11: 46 | int 1 47 | return 48 | main_l12: 49 | int 1 50 | return 51 | main_l13: 52 | txn Sender 53 | global CreatorAddress 54 | == 55 | return 56 | main_l14: 57 | txn Sender 58 | global CreatorAddress 59 | == 60 | return 61 | main_l15: 62 | int 1 63 | return 64 | sub0: // int_to_ascii 65 | store 3 66 | byte "0123456789" 67 | load 3 68 | load 3 69 | int 1 70 | + 71 | substring3 72 | retsub 73 | sub1: // itoa 74 | store 2 75 | load 2 76 | int 0 77 | == 78 | bnz sub1_l5 79 | load 2 80 | int 10 81 | / 82 | int 0 83 | > 84 | bnz sub1_l4 85 | byte "" 86 | sub1_l3: 87 | load 2 88 | int 10 89 | % 90 | callsub sub0 91 | concat 92 | b sub1_l6 93 | sub1_l4: 94 | load 2 95 | int 10 96 | / 97 | load 2 98 | swap 99 | callsub sub1 100 | swap 101 | store 2 102 | b sub1_l3 103 | sub1_l5: 104 | byte "0" 105 | sub1_l6: 106 | retsub 107 | sub2: // sing 108 | store 1 109 | load 1 110 | callsub sub1 111 | byte " Bottles of beer on the wall" 112 | concat 113 | log 114 | load 1 115 | callsub sub1 116 | byte " Bottles of beer" 117 | concat 118 | log 119 | byte "Take one down, pass it around" 120 | log 121 | load 1 122 | int 1 123 | - 124 | callsub sub1 125 | byte " Bottles of beer on the wall" 126 | concat 127 | log 128 | retsub -------------------------------------------------------------------------------- /examples/avm/logs/clear.teal: -------------------------------------------------------------------------------- 1 | #pragma version 5 2 | int 1 3 | return -------------------------------------------------------------------------------- /examples/avm/op-pool/approval.teal: -------------------------------------------------------------------------------- 1 | #pragma version 5 2 | txn ApplicationID 3 | int 0 4 | == 5 | bnz main_l14 6 | txn OnCompletion 7 | int DeleteApplication 8 | == 9 | bnz main_l13 10 | txn OnCompletion 11 | int UpdateApplication 12 | == 13 | bnz main_l12 14 | txn OnCompletion 15 | int CloseOut 16 | == 17 | bnz main_l11 18 | txn OnCompletion 19 | int OptIn 20 | == 21 | bnz main_l10 22 | txn NumAppArgs 23 | int 0 24 | > 25 | bnz main_l9 26 | txn NumAppArgs 27 | int 0 28 | == 29 | bnz main_l8 30 | err 31 | main_l8: 32 | int 1 33 | return 34 | main_l9: 35 | txna ApplicationArgs 0 36 | txna ApplicationArgs 1 37 | txn Sender 38 | ed25519verify 39 | pop 40 | int 1 41 | return 42 | main_l10: 43 | int 1 44 | return 45 | main_l11: 46 | int 1 47 | return 48 | main_l12: 49 | txn Sender 50 | global CreatorAddress 51 | == 52 | return 53 | main_l13: 54 | txn Sender 55 | global CreatorAddress 56 | == 57 | return 58 | main_l14: 59 | int 1 60 | return -------------------------------------------------------------------------------- /examples/avm/op-pool/clear.teal: -------------------------------------------------------------------------------- 1 | #pragma version 5 2 | int 1 3 | return -------------------------------------------------------------------------------- /examples/kmd/KmdExample.php: -------------------------------------------------------------------------------- 1 | 'test1', 43 | 'wallet_password' => 'test', 44 | 'wallet_driver_name' => 'sqlite', 45 | ]); 46 | 47 | try { 48 | $result = $algorand->kmd()->createWallet($request); 49 | print_r($result); 50 | } catch (Exception $e) { 51 | echo 'Exception when calling DefaultApi->createWallet: ', $e->getMessage(), PHP_EOL; 52 | } 53 | } 54 | 55 | public static function versions(Algorand $algorand) 56 | { 57 | try { 58 | $result = $algorand->kmd()->getVersion(); 59 | print_r($result); 60 | } catch (Exception $e) { 61 | echo 'Exception when calling DefaultApi->getVersion(): ', $e->getMessage(), PHP_EOL; 62 | } 63 | } 64 | 65 | public static function swagger(Algorand $algorand) 66 | { 67 | try { 68 | $result = $algorand->kmd()->swaggerHandler(); 69 | print_r($result); 70 | } catch (Exception $e) { 71 | echo 'Exception when calling DefaultApi->getVersion(): ', $e->getMessage(), PHP_EOL; 72 | } 73 | } 74 | 75 | public static function listWallets(Algorand $algorand) 76 | { 77 | try { 78 | $result = $algorand->kmd()->listWallets(); 79 | print_r($result); 80 | } catch (Exception $e) { 81 | echo 'Exception when calling DefaultApi->getVersion(): ', $e->getMessage(), PHP_EOL; 82 | } 83 | } 84 | } 85 | 86 | KmdExample::main(); 87 | 88 | function prettyPrint($data) 89 | { 90 | echo $data . PHP_EOL; 91 | } 92 | -------------------------------------------------------------------------------- /examples/multisig/MultiSigExample.php: -------------------------------------------------------------------------------- 1 | getPublicAddress()); 28 | prettyPrint('Account 2: ' . $accountB->getPublicAddress()); 29 | prettyPrint('Account 3: ' . $accountC->getPublicAddress()); 30 | 31 | $publicKeys = array_map(fn (Account $value) => new Ed25519PublicKey($value->getPublicKey()), [$accountA, $accountB, $accountC]); 32 | $msa = new MultiSignatureAddress(1, 2, $publicKeys); 33 | prettyPrint('Multisig Address: ' . $msa->toAddress()->encodedAddress); 34 | 35 | // Get the suggested transaction params 36 | $params = $algorand->getSuggestedTransactionParams(); 37 | 38 | // Create the transaction 39 | $transaction = TransactionBuilder::payment() 40 | ->sender($msa->toAddress()) 41 | ->noteText('Multisig example') 42 | ->amount(1000) // 0.001 Algo 43 | ->receiver($accountC->getAddress()) 44 | ->suggestedParams($params) 45 | ->build(); 46 | 47 | // Sign the transaction 48 | $signedTx = $msa->sign($accountA, $transaction); 49 | $completeTx = $msa->append($accountB, $signedTx); 50 | 51 | // Broadcast the transaction 52 | $txId = $algorand->sendTransaction($completeTx); 53 | prettyPrint('Transaction id: ' . $txId); 54 | prettyPrint('Waiting for confirmation'); 55 | $response = $algorand->waitForConfirmation($txId); 56 | prettyPrint('Multisig transaction confirmed in round ' . $response->confirmedRound); 57 | } 58 | } 59 | 60 | MultiSigExample::main(); 61 | 62 | function prettyPrint($data) 63 | { 64 | echo $data . PHP_EOL; 65 | } 66 | -------------------------------------------------------------------------------- /examples/offline/OfflineTransactionExample.php: -------------------------------------------------------------------------------- 1 | getPublicAddress()); 27 | 28 | // Export the transaction 29 | self::exportTransaction($algorand, $account, 'signed.txn'); 30 | 31 | // Import the transaction 32 | $signedTx = self::importTransaction('signed.txn'); 33 | 34 | // Broadcast the imported transaction 35 | $txId = $algorand->sendTransaction($signedTx); 36 | prettyPrint('Transaction id: ' . $txId); 37 | prettyPrint('Waiting for confirmation'); 38 | $response = $algorand->waitForConfirmation($txId); 39 | prettyPrint('Transaction confirmed in round ' . $response->confirmedRound); 40 | } 41 | 42 | public static function exportTransaction(Algorand $algorand, Account $account, string $fileName) 43 | { 44 | $receiver = Address::fromAlgorandAddress('L5EUPCF4ROKNZMAE37R5FY2T5DF2M3NVYLPKSGWTUKVJRUGIW4RKVPNPD4'); 45 | 46 | // Get the suggested parameters 47 | $params = $algorand->getSuggestedTransactionParams(); 48 | 49 | // Create the transaction 50 | $transaction = TransactionBuilder::payment() 51 | ->sender($account->getAddress()) 52 | ->receiver($receiver) 53 | ->noteText('Hello world') 54 | ->amount(1000) // 0.001 Algo 55 | ->suggestedParams($params) 56 | ->build(); 57 | 58 | // Sign the transaction 59 | $signedTx = $transaction->sign($account); 60 | 61 | // Export the transaction 62 | $signedTx->export($fileName); 63 | } 64 | 65 | public static function importTransaction(string $fileName) : SignedTransaction 66 | { 67 | // Import the transaction 68 | $data = file_get_contents($fileName); 69 | 70 | // Decode the messagepack to a signed transaction 71 | /** @var SignedTransaction $signedTx */ 72 | $signedTx = Encoder::getInstance()->decodeMessagePack($data, SignedTransaction::class); 73 | 74 | return $signedTx; 75 | } 76 | } 77 | 78 | OfflineTransactionExample::main(); 79 | 80 | function prettyPrint($data) 81 | { 82 | echo $data . PHP_EOL; 83 | } 84 | -------------------------------------------------------------------------------- /examples/smart-contracts/AccountDelegationExample.php: -------------------------------------------------------------------------------- 1 | getPublicAddress()); 25 | 26 | $arguments = [BigInteger::of(123)->toBytes()]; 27 | 28 | $result = $algorand->applicationManager()->compileTEAL(self::$sampleArgsTeal); 29 | $lsig = LogicSignature::fromProgram($result->program(), $arguments)->sign($account); 30 | $receiver = 'KTFZ5SQU3AQ6UFYI2QOWF5X5XJTAFRHACWHXAZV6CPLNKS2KSGQWPT4ACE'; 31 | 32 | $transaction = TransactionBuilder::payment() 33 | ->sender($account->getAddress()) 34 | ->note('Account delegation') 35 | ->amount(1000) 36 | ->receiver(Address::fromAlgorandAddress($receiver)) 37 | ->useSuggestedParams($algorand) 38 | ->build(); 39 | 40 | // Sign the logic transaction 41 | $signedTx = $lsig->signTransaction($transaction); 42 | 43 | // Send the transaction 44 | $txId = $algorand->sendTransaction($signedTx); 45 | prettyPrint('Transaction id: ' . $txId); 46 | prettyPrint('Waiting for confirmation'); 47 | $response = $algorand->waitForConfirmation($txId); 48 | prettyPrint('Account delegation confirmed in round ' . $response->confirmedRound); 49 | } 50 | 51 | private static $sampleArgsTeal = '// samplearg.teal 52 | // This code is meant for learning purposes only 53 | // It should not be used in production 54 | arg_0 55 | btoi 56 | int 123 57 | =='; 58 | } 59 | 60 | AccountDelegationExample::main(); 61 | 62 | function prettyPrint($data) 63 | { 64 | echo $data . PHP_EOL; 65 | } 66 | -------------------------------------------------------------------------------- /examples/smart-contracts/CompileTEALExample.php: -------------------------------------------------------------------------------- 1 | applicationManager()->compileTEAL(self::$sampleArgsTeal); 21 | 22 | prettyPrint('Hash: ' . $result->hash); 23 | prettyPrint('Result: ' . $result->result); 24 | prettyPrint('Program: ' . $result->program()->bytes()); 25 | } 26 | 27 | private static $sampleArgsTeal = '// samplearg.teal 28 | // This code is meant for learning purposes only 29 | // It should not be used in production 30 | arg_0 31 | btoi 32 | int 123 33 | =='; 34 | } 35 | 36 | CompileTEALExample::main(); 37 | 38 | function prettyPrint($data) 39 | { 40 | echo $data . PHP_EOL; 41 | } 42 | -------------------------------------------------------------------------------- /examples/smart-contracts/ContractAccountExample.php: -------------------------------------------------------------------------------- 1 | getPublicAddress()); 25 | 26 | // Compile TEAL 27 | prettyPrint('Compiling TEAL code'); 28 | $arguments = [BigInteger::of(123)->toBytes()]; 29 | $result = $algorand->applicationManager()->compileTEAL(self::$sampleArgsTeal); 30 | $lsig = LogicSignature::fromProgram($result->program(), $arguments); 31 | 32 | $receiver = Address::fromAlgorandAddress('KTFZ5SQU3AQ6UFYI2QOWF5X5XJTAFRHACWHXAZV6CPLNKS2KSGQWPT4ACE'); 33 | $transaction = TransactionBuilder::payment() 34 | ->sender($lsig->toAddress()) 35 | ->note('Contract account') 36 | ->amount(1000) 37 | ->receiver($receiver) 38 | ->useSuggestedParams($algorand) 39 | ->build(); 40 | 41 | // Sign the logic transaction 42 | $signedTx = $lsig->signTransaction($transaction); 43 | 44 | // Send the transaction 45 | $txId = $algorand->sendTransaction($signedTx); 46 | prettyPrint('Transaction id: ' . $txId); 47 | prettyPrint('Waiting for confirmation'); 48 | $response = $algorand->waitForConfirmation($txId); 49 | prettyPrint('Account delegation confirmed in round ' . $response->confirmedRound); 50 | } 51 | 52 | private static $sampleArgsTeal = '// samplearg.teal 53 | // This code is meant for learning purposes only 54 | // It should not be used in production 55 | arg_0 56 | btoi 57 | int 123 58 | =='; 59 | } 60 | 61 | ContractAccountExample::main(); 62 | 63 | function prettyPrint($data) 64 | { 65 | echo $data . PHP_EOL; 66 | } 67 | -------------------------------------------------------------------------------- /examples/start-building/YourFirstTransactionExample.php: -------------------------------------------------------------------------------- 1 | getPublicAddress()); 25 | 26 | // Specify the receiver 27 | $receiver = Address::fromAlgorandAddress('KTFZ5SQU3AQ6UFYI2QOWF5X5XJTAFRHACWHXAZV6CPLNKS2KSGQWPT4ACE'); 28 | 29 | // Create a payment transaction 30 | $transaction = TransactionBuilder::payment() 31 | ->sender($account->getAddress()) 32 | ->note('Your first transaction') 33 | ->amount(1000) 34 | ->receiver($receiver) 35 | ->useSuggestedParams($algorand) 36 | ->build(); 37 | 38 | // Sign the transaction 39 | $signedTx = $transaction->sign($account); 40 | 41 | // Submit the transaction to the network 42 | $txId = $algorand->sendTransaction($signedTx); 43 | prettyPrint('Transaction id: ' . $txId); 44 | prettyPrint('Waiting for confirmation'); 45 | $response = $algorand->waitForConfirmation($txId); 46 | prettyPrint('Transaction confirmed in round ' . $response->confirmedRound); 47 | } 48 | } 49 | 50 | YourFirstTransactionExample::main(); 51 | 52 | function prettyPrint($data) 53 | { 54 | echo $data . PHP_EOL; 55 | } 56 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | 18 | src/ 19 | 20 | 21 | 22 | 23 | ./tests/Unit 24 | 25 | 26 | ./tests/Feature 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /psalm.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/AlgorandServiceProvider.php: -------------------------------------------------------------------------------- 1 | registerPublishables(); 16 | } 17 | 18 | public function register() 19 | { 20 | $this->mergeConfigFrom(__DIR__.'/config/algorand.php', 'algorand'); 21 | 22 | $this->app->singleton(Algorand::class, function ($app) { 23 | $algodUrl = config('algorand.algod.api_url', AlgoExplorer::TESTNET_ALGOD_API_URL); 24 | $algodApiKey = config('algorand.algod.api_key', ''); 25 | $algodTokenHeader = config('algorand.algod.api_token_header', AlgodClient::ALGOD_API_TOKEN); 26 | 27 | $indexerUrl = config('algorand.indexer.api_url', AlgoExplorer::TESTNET_INDEXER_API_URL); 28 | $indexerApiKey = config('algorand.indexer.api_key', ''); 29 | $indexerTokenHeader = config('algorand.indexer.api_token_header', IndexerClient::INDEXER_API_TOKEN); 30 | 31 | $kmdUrl = config('algorand.kmd.api_url', '127.0.0.1'); 32 | $kmdApiKey = config('algorand.kmd.api_key', ''); 33 | $kmdTokenHeader = config('algorand.kmd.api_token_header', KmdClient::KMD_API_TOKEN); 34 | 35 | $algodClient = new AlgodClient($algodUrl, $algodApiKey, $algodTokenHeader); 36 | $indexerClient = new IndexerClient($indexerUrl, $indexerApiKey, $indexerTokenHeader); 37 | $kmdClient = new KmdClient($kmdUrl, $kmdApiKey, $kmdTokenHeader); 38 | 39 | return new Algorand($algodClient, $indexerClient, $kmdClient); 40 | }); 41 | } 42 | 43 | protected function registerPublishables() 44 | { 45 | // php artisan vendor:publish --provider="Rootsoft\Algorand\AlgorandServiceProvider" --tag="config" 46 | if ($this->app->runningInConsole()) { 47 | $this->publishes([ 48 | __DIR__.'/config/algorand.php' => config_path('algorand.php'), 49 | ], 'config'); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/Clients/AlgoExplorer.php: -------------------------------------------------------------------------------- 1 | setHost($apiUrl)->setApiKey($tokenKey, $apiKey); 38 | 39 | $this->api = new KmdApi( 40 | $this->client, 41 | $config 42 | ); 43 | } 44 | 45 | /** 46 | * @return KmdApi 47 | */ 48 | public function getApi(): KmdApi 49 | { 50 | return $this->api; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/Clients/PureStake.php: -------------------------------------------------------------------------------- 1 | bytes = $bytes; 27 | } 28 | 29 | /** 30 | * @return string 31 | */ 32 | public function bytes(): string 33 | { 34 | return $this->bytes; 35 | } 36 | 37 | public function toMessagePack(): array 38 | { 39 | return [ 40 | 'bytes' => $this->bytes, 41 | ]; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Crypto/MultiSignature.php: -------------------------------------------------------------------------------- 1 | version = $version; 30 | $this->threshold = $threshold; 31 | $this->subsigs = $subsigs; 32 | } 33 | 34 | /** 35 | * Performs signature verification. 36 | * 37 | * @param string $data 38 | * @return bool 39 | * @throws \SodiumException 40 | */ 41 | public function verify(string $data):bool 42 | { 43 | if ($this->version != self::MULTISIG_VERSION || $this->threshold <= 0 || empty($this->subsigs)) { 44 | return false; 45 | } 46 | 47 | if ($this->threshold > count($this->subsigs)) { 48 | return false; 49 | } 50 | 51 | $verifiedCount = 0; 52 | 53 | for ($i = 0; $i < count($this->subsigs); $i++) { 54 | $subsig = $this->subsigs[$i]; 55 | $signature = $subsig->getSignature(); 56 | if (is_null($signature)) { 57 | continue; 58 | } 59 | 60 | $pk = Address::fromPublicKey($subsig->getPublicKey()->bytes()); 61 | $verified = CryptoUtils::verify($data, $signature->bytes(), $pk->address); 62 | if ($verified) { 63 | $verifiedCount += 1; 64 | } 65 | } 66 | 67 | return $verifiedCount >= $this->threshold; 68 | } 69 | 70 | /** 71 | * @return int 72 | */ 73 | public function getVersion(): int 74 | { 75 | return $this->version; 76 | } 77 | 78 | /** 79 | * @return int 80 | */ 81 | public function getThreshold(): int 82 | { 83 | return $this->threshold; 84 | } 85 | 86 | /** 87 | * Add a multisig sub signature. 88 | * @param MultisigSubsig $subsig 89 | */ 90 | public function addSubsig(MultisigSubsig $subsig) 91 | { 92 | $this->subsigs[] = $subsig; 93 | } 94 | 95 | /** 96 | * Updates a multisig subsig at the given index. 97 | * @param int $index 98 | * @param MultisigSubsig $subsig 99 | */ 100 | public function updateSubsig(int $index, MultisigSubsig $subsig) 101 | { 102 | $this->subsigs[$index] = $subsig; 103 | } 104 | 105 | /** 106 | * @return array|MultisigSubsig[] 107 | */ 108 | public function getSubsigs(): array 109 | { 110 | return $this->subsigs; 111 | } 112 | 113 | public function toMessagePack(): array 114 | { 115 | return [ 116 | 'v' => $this->version, 117 | 'thr' => $this->threshold, 118 | 'subsig' => $this->subsigs, 119 | ]; 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /src/Crypto/MultisigSubsig.php: -------------------------------------------------------------------------------- 1 | publicKey = $publicKey; 23 | $this->signature = $signature; 24 | } 25 | 26 | /** 27 | * @return Ed25519PublicKey 28 | */ 29 | public function getPublicKey(): Ed25519PublicKey 30 | { 31 | return $this->publicKey; 32 | } 33 | 34 | /** 35 | * @param Signature|null $signature 36 | */ 37 | public function setSignature(?Signature $signature): void 38 | { 39 | $this->signature = $signature; 40 | } 41 | 42 | /** 43 | * @return Signature|null 44 | */ 45 | public function getSignature(): ?Signature 46 | { 47 | return $this->signature; 48 | } 49 | 50 | public function toMessagePack(): array 51 | { 52 | return [ 53 | 'pk' => $this->publicKey->bytes(), 54 | 's' => isset($this->signature) ? $this->signature->bytes() : null, 55 | ]; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/Crypto/Signature.php: -------------------------------------------------------------------------------- 1 | bytes = $bytes; 24 | } 25 | 26 | /** 27 | * @return string 28 | */ 29 | public function bytes(): string 30 | { 31 | return $this->bytes; 32 | } 33 | 34 | public function toMessagePack(): array 35 | { 36 | return [ 37 | 'bytes' => $this->bytes, 38 | ]; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Exceptions/AlgorandException.php: -------------------------------------------------------------------------------- 1 | error_message = $error_message; 23 | } 24 | 25 | /** 26 | * Get the error message. 27 | * 28 | * @return mixed 29 | */ 30 | public function getErrorMessage() 31 | { 32 | return $this->error_message; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Exceptions/ApiKeyException.php: -------------------------------------------------------------------------------- 1 | indexerClient = $indexerClient; 45 | $this->jsonMapper = $jsonMapper; 46 | } 47 | 48 | /** 49 | * Allow searching all transactions that have occurred on the blockchain. 50 | * This call contains many parameters to refine the search for specific values. 51 | * 52 | * @return TransactionQueryBuilder 53 | */ 54 | public function transactions(): TransactionQueryBuilder 55 | { 56 | return new TransactionQueryBuilder($this->indexerClient, $this->jsonMapper); 57 | } 58 | 59 | /** 60 | * Allow searching all assets that have occurred on the blockchain. 61 | * This call contains many parameters to refine the search for specific values. 62 | * 63 | * @return AssetQueryBuilder 64 | */ 65 | public function assets(): AssetQueryBuilder 66 | { 67 | return new AssetQueryBuilder($this->indexerClient, $this->jsonMapper); 68 | } 69 | 70 | /** 71 | * Allow searching all accounts on the blockchain. 72 | * This call contains many parameters to refine the search for specific values. 73 | * 74 | * @return AccountQueryBuilder 75 | */ 76 | public function accounts(): AccountQueryBuilder 77 | { 78 | return new AccountQueryBuilder($this->indexerClient, $this->jsonMapper); 79 | } 80 | 81 | /** 82 | * Allow searching all applications on the blockchain. 83 | * This call contains many parameters to refine the search for specific values. 84 | * 85 | * @return ApplicationQueryBuilder 86 | */ 87 | public function applications(): ApplicationQueryBuilder 88 | { 89 | return new ApplicationQueryBuilder($this->indexerClient, $this->jsonMapper); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/Indexer/Builders/ApplicationQueryBuilder.php: -------------------------------------------------------------------------------- 1 | setParameter('application-id', $applicationId); 37 | 38 | return $this; 39 | } 40 | 41 | /** 42 | * Fetch the applications. 43 | * 44 | * @param int|null $limit 45 | * @return SearchApplicationsResult 46 | * @throws \Rootsoft\Algorand\Exceptions\AlgorandException 47 | */ 48 | public function search(?int $limit = null) 49 | { 50 | if (! is_null($limit)) { 51 | $this->limit($limit); 52 | } 53 | 54 | return $this->searchApplications($this->payload); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/Indexer/QueryBuilder.php: -------------------------------------------------------------------------------- 1 | indexerClient = $client; 26 | $this->jsonMapper = $jsonMapper; 27 | } 28 | 29 | /** 30 | * The next page of results. Use the next token provided by the previous results. 31 | * 32 | * @param string $next 33 | * @return $this 34 | */ 35 | public function next(string $next) 36 | { 37 | $this->setParameter('next', $next); 38 | 39 | return $this; 40 | } 41 | 42 | /** 43 | * Maximum number of results to return. 44 | * 45 | * @param int $limit 46 | * @return $this 47 | */ 48 | public function limit(int $limit) 49 | { 50 | $this->setParameter('limit', $limit); 51 | 52 | return $this; 53 | } 54 | 55 | /** 56 | * Set parameters. 57 | * 58 | * @param string $key 59 | * @param mixed $value 60 | * 61 | * @return $this 62 | */ 63 | public function setParameter(string $key, $value) 64 | { 65 | Arr::set($this->payload, $key, $value); 66 | 67 | return $this; 68 | } 69 | 70 | /** 71 | * Get parameters. 72 | * 73 | * @param string $key 74 | * @param mixed $default 75 | * 76 | * @return mixed 77 | */ 78 | public function getParameter(string $key, $default = null) 79 | { 80 | return Arr::get($this->payload, $key, $default); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/Indexer/Services/ManagesIndexerAccountsV2.php: -------------------------------------------------------------------------------- 1 | get($this->indexerClient, "/v2/accounts/$address/created-assets", $params); 23 | 24 | $result = new SearchAssetsResult(); 25 | $this->jsonMapper->mapObject($response, $result); 26 | 27 | return $result; 28 | } 29 | 30 | /** 31 | * Search accounts using the indexer. 32 | * 33 | * @param array $queryParams 34 | * @return SearchAccountsResult List of accounts. 35 | */ 36 | protected function searchAccounts(array $queryParams) 37 | { 38 | if (array_key_exists('balance-asset-id', $queryParams)) { 39 | $balanceAssetId = $queryParams['balance-asset-id']; 40 | //unset($queryParams['balance-asset-id']); 41 | return $this->searchAccountForBalances($balanceAssetId, $queryParams); 42 | } 43 | 44 | $response = $this->get($this->indexerClient, '/v2/accounts', $queryParams); 45 | 46 | $result = new SearchAccountsResult(); 47 | $this->jsonMapper->mapObject($response, $result); 48 | 49 | return $result; 50 | } 51 | 52 | /** 53 | * Lookup the list of accounts who hold this asset. 54 | * 55 | * @param int $assetId 56 | * @param array $queryParams 57 | * @return SearchAccountsResult List of accounts. 58 | */ 59 | protected function searchAccountForBalances(int $assetId, array $queryParams) 60 | { 61 | $response = $this->get($this->indexerClient, "/v2/assets/$assetId/balances", $queryParams); 62 | 63 | $result = new SearchAccountsResult(); 64 | $this->jsonMapper->mapObject($response, $result); 65 | 66 | return $result; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/Indexer/Services/ManagesIndexerApplicationsV2.php: -------------------------------------------------------------------------------- 1 | get($this->indexerClient, "/v2/applications/$applicationId"); 26 | 27 | $application = new ApplicationResult(); 28 | $this->jsonMapper->mapObject($response, $application); 29 | 30 | return $application; 31 | } 32 | 33 | /** 34 | * Lookup application logs by a given application id. 35 | * 36 | * @param int $applicationId 37 | * @return \Rootsoft\Algorand\Models\Applications\ApplicationLogsResult 38 | * @throws AlgorandException 39 | */ 40 | public function getApplicationLogsById(int $applicationId): ApplicationLogsResult 41 | { 42 | $response = $this->get($this->indexerClient, "/v2/applications/$applicationId/logs"); 43 | 44 | $result = new ApplicationLogsResult(); 45 | $this->jsonMapper->mapObject($response, $result); 46 | 47 | return $result; 48 | } 49 | 50 | /** 51 | * Search applications using the indexer. 52 | * 53 | * @param array $queryParams 54 | * @return SearchApplicationsResult List of applications. 55 | * @throws \Rootsoft\Algorand\Exceptions\AlgorandException 56 | */ 57 | protected function searchApplications(array $queryParams) 58 | { 59 | $response = $this->get($this->indexerClient, '/v2/applications', $queryParams); 60 | 61 | $result = new SearchApplicationsResult(); 62 | $this->jsonMapper->mapObject($response, $result); 63 | 64 | return $result; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/Indexer/Services/ManagesIndexerAssetsV2.php: -------------------------------------------------------------------------------- 1 | get($this->indexerClient, '/v2/assets', $queryParams); 18 | 19 | $result = new SearchAssetsResult(); 20 | $this->jsonMapper->mapObject($response, $result); 21 | 22 | return $result; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Indexer/Services/ManagesIndexerTransactionsV2.php: -------------------------------------------------------------------------------- 1 | searchTransactionsForAsset($queryParams['for_asset_id'], $queryParams); 19 | } elseif (array_key_exists('for_account_id', $queryParams)) { 20 | return $this->searchTransactionsForAccount($queryParams['for_account_id'], $queryParams); 21 | } 22 | 23 | $response = $this->get($this->indexerClient, '/v2/transactions', $queryParams); 24 | 25 | $result = new SearchTransactionsResult(); 26 | $this->jsonMapper->mapObject($response, $result); 27 | 28 | return $result; 29 | } 30 | 31 | /** 32 | * Lookup transactions for an asset using the indexer. 33 | * 34 | * @param int $assetId 35 | * @param array $queryParams 36 | * @return SearchTransactionsResult List of transactions. 37 | */ 38 | protected function searchTransactionsForAsset(int $assetId, array $queryParams) 39 | { 40 | $response = $this->get($this->indexerClient, "/v2/assets/$assetId/transactions", $queryParams); 41 | 42 | $result = new SearchTransactionsResult(); 43 | $this->jsonMapper->mapObject($response, $result); 44 | 45 | return $result; 46 | } 47 | 48 | /** 49 | * Lookup transactions for an account using the indexer. 50 | * 51 | * @param string $accountId 52 | * @param array $queryParams 53 | * @return SearchTransactionsResult List of transactions. 54 | */ 55 | protected function searchTransactionsForAccount(string $accountId, array $queryParams) 56 | { 57 | $response = $this->get($this->indexerClient, "/v2/accounts/$accountId/transactions", $queryParams); 58 | 59 | $result = new SearchTransactionsResult(); 60 | $this->jsonMapper->mapObject($response, $result); 61 | 62 | return $result; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/Indexer/Services/ManagesIndexerV2.php: -------------------------------------------------------------------------------- 1 | get($this->indexerClient, '/health'); 19 | 20 | $health = new IndexerHealth(); 21 | $this->jsonMapper->mapObject($response, $health); 22 | 23 | return $health; 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/KMD/HeaderSelector.php: -------------------------------------------------------------------------------- 1 | selectAcceptHeader($accept); 49 | if ($accept !== null) { 50 | $headers['Accept'] = $accept; 51 | } 52 | 53 | $headers['Content-Type'] = $this->selectContentTypeHeader($contentTypes); 54 | 55 | return $headers; 56 | } 57 | 58 | /** 59 | * @param string[] $accept 60 | * @return array 61 | */ 62 | public function selectHeadersForMultipart($accept) 63 | { 64 | $headers = $this->selectHeaders($accept, []); 65 | 66 | unset($headers['Content-Type']); 67 | 68 | return $headers; 69 | } 70 | 71 | /** 72 | * Return the header 'Accept' based on an array of Accept provided. 73 | * 74 | * @param string[] $accept Array of header 75 | * 76 | * @return null|string Accept (e.g. application/json) 77 | */ 78 | private function selectAcceptHeader($accept) 79 | { 80 | if (count($accept) === 0 || (count($accept) === 1 && $accept[0] === '')) { 81 | return null; 82 | } elseif ($jsonAccept = preg_grep('~(?i)^(application/json|[^;/ \t]+/[^;/ \t]+[+]json)[ \t]*(;.*)?$~', $accept)) { 83 | return implode(',', $jsonAccept); 84 | } else { 85 | return implode(',', $accept); 86 | } 87 | } 88 | 89 | /** 90 | * Return the content type based on an array of content-type provided. 91 | * 92 | * @param string[] $contentType Array fo content-type 93 | * 94 | * @return string Content-Type (e.g. application/json) 95 | */ 96 | private function selectContentTypeHeader($contentType) 97 | { 98 | if (count($contentType) === 0 || (count($contentType) === 1 && $contentType[0] === '')) { 99 | return 'application/json'; 100 | } elseif (preg_grep("/application\/json/i", $contentType)) { 101 | return 'application/json'; 102 | } else { 103 | return implode(',', $contentType); 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /src/KMD/Model/ModelInterface.php: -------------------------------------------------------------------------------- 1 | algodClient = $algodClient; 50 | $this->jsonMapper = $jsonMapper; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/Managers/ApplicationManager.php: -------------------------------------------------------------------------------- 1 | algodClient = $algodClient; 41 | $this->jsonMapper = $jsonMapper; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Managers/AssetManager.php: -------------------------------------------------------------------------------- 1 | algodClient = $algodClient; 59 | $this->indexerClient = $indexerClient; 60 | $this->jsonMapper = $jsonMapper; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/Mnemonic/SeedPhrase.php: -------------------------------------------------------------------------------- 1 | 8 | * 9 | * For the full copyright and license information, please view the LICENSE 10 | * file that was distributed with this source code or visit following link: 11 | * https://github.com/furqansiddiqui/bip39-mnemonics-php/blob/master/LICENSE 12 | */ 13 | 14 | namespace Rootsoft\Algorand\Mnemonic; 15 | 16 | class SeedPhrase 17 | { 18 | public const MNEMONIC_DELIM = ' '; 19 | 20 | /** @var string */ 21 | public $entropy; 22 | 23 | /** @var int */ 24 | public $wordsCount; 25 | 26 | /** @var array */ 27 | public $wordsIndex; 28 | 29 | /** @var array */ 30 | public $words; 31 | 32 | /** @var array */ 33 | public $rawBinaryChunks; 34 | 35 | /** 36 | * Mnemonic constructor. 37 | * @param string|null $entropy 38 | */ 39 | public function __construct(?string $entropy = null) 40 | { 41 | $this->entropy = $entropy; 42 | $this->wordsCount = 0; 43 | $this->wordsIndex = []; 44 | $this->words = []; 45 | $this->rawBinaryChunks = []; 46 | } 47 | 48 | /** 49 | * @param string $passphrase 50 | * @param int $bytes 51 | * @return string 52 | */ 53 | public function generateSeed(string $passphrase = '', int $bytes = 0): string 54 | { 55 | return hash_pbkdf2( 56 | 'sha512', 57 | implode(' ', $this->words), 58 | 'mnemonic'.$passphrase, 59 | 2048, 60 | $bytes 61 | ); 62 | } 63 | 64 | /** 65 | * Return a human-readable string representation of the words. 66 | */ 67 | public function format() 68 | { 69 | return implode(self::MNEMONIC_DELIM, $this->words); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/Models/AccountParticipation.php: -------------------------------------------------------------------------------- 1 | numUint = $numUint; 39 | $this->numByteSlice = $numByteSlice; 40 | } 41 | 42 | public function toMessagePack(): array 43 | { 44 | return [ 45 | 'nui' => $this->numUint, 46 | 'nbs' => $this->numByteSlice, 47 | ]; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/Models/Applications/TEALProgram.php: -------------------------------------------------------------------------------- 1 | program = $program; 24 | } 25 | 26 | /** 27 | * Create a new, TEAL program from the given source code. 28 | * 29 | * @param string $source 30 | * @return TEALProgram 31 | */ 32 | public static function fromSourceCode(string $source): self 33 | { 34 | return new self(utf8_encode($source)); 35 | } 36 | 37 | /** 38 | * Get the program bytes. 39 | * 40 | * @return string 41 | */ 42 | public function bytes(): string 43 | { 44 | return $this->program; 45 | } 46 | 47 | /** 48 | * Creates Signature compatible with ed25519verify TEAL opcode from data and program bytes. 49 | * 50 | * @param Account $account 51 | * @param string $data 52 | * @return Signature 53 | * @throws \Rootsoft\Algorand\Exceptions\AlgorandException 54 | * @throws \SodiumException 55 | */ 56 | public function sign(Account $account, string $data) : Signature 57 | { 58 | $lsig = new LogicSignature($this->program); 59 | 60 | return $lsig->toAddress()->sign($account, $data); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/Models/AssetHolding.php: -------------------------------------------------------------------------------- 1 | allocations = $allocations; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Models/Indexer/IndexerHealth.php: -------------------------------------------------------------------------------- 1 | bytes = $bytes; 28 | } 29 | 30 | /** 31 | * Get the bytes for this participation key. 32 | * @return string 33 | */ 34 | public function getBytes(): string 35 | { 36 | return $this->bytes; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Models/Keys/VRFPublicKey.php: -------------------------------------------------------------------------------- 1 | bytes = $bytes; 28 | } 29 | 30 | /** 31 | * Get the bytes for this vrf key. 32 | * @return string 33 | */ 34 | public function getBytes(): string 35 | { 36 | return $this->bytes; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Models/Ledgers/LedgerSupplyResult.php: -------------------------------------------------------------------------------- 1 | $this->accounts, 66 | 'apps' => $this->apps, 67 | 'latest-timestamp' => $this->latestTimestamp, 68 | 'protocol-version' => $this->protocolVersion, 69 | 'round' => $this->round, 70 | 'sources' => $this->sources, 71 | 'txns' => $this->txns, 72 | ]; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/Models/Teals/DryrunResponse.php: -------------------------------------------------------------------------------- 1 | result); 28 | } 29 | 30 | /// Get the compiled TEAL program. 31 | public function program(): TEALProgram 32 | { 33 | return new TEALProgram($this->bytes()); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Models/Transactions/ApplicationTransactionResult.php: -------------------------------------------------------------------------------- 1 | applicationTransaction = new ApplicationCreateTransaction(); 20 | parent::__construct($this->applicationTransaction, OnCompletion::NO_OP_OC()); 21 | } 22 | 23 | /** 24 | * Holds the maximum number of local state values defined within aStateSchema object. 25 | * 26 | * @param StateSchema|null $localStateSchema 27 | * @return $this 28 | */ 29 | public function localStateSchema(?StateSchema $localStateSchema): self 30 | { 31 | $this->applicationTransaction->localStateSchema = $localStateSchema; 32 | 33 | return $this; 34 | } 35 | 36 | /** 37 | * Holds the maximum number of global state values defined within aStateSchema object. 38 | * 39 | * @param StateSchema|null $globalStateSchema 40 | * @return $this 41 | */ 42 | public function globalStateSchema(?StateSchema $globalStateSchema): self 43 | { 44 | $this->applicationTransaction->globalStateSchema = $globalStateSchema; 45 | 46 | return $this; 47 | } 48 | 49 | /** 50 | * Number of additional pages allocated to the application's approval and clear state programs. 51 | * Each ExtraProgramPages is 2048 bytes. 52 | * 53 | * The sum of ApprovalProgram and ClearStateProgram may not exceed 2048*(1+ExtraProgramPages) bytes. 54 | * 55 | * @param int|null $extraPages 56 | * @return ApplicationCreateTransactionBuilder 57 | */ 58 | public function extraPages(?int $extraPages): self 59 | { 60 | $this->applicationTransaction->extraPages = $extraPages; 61 | 62 | return $this; 63 | } 64 | 65 | /** 66 | * @return ApplicationCreateTransaction 67 | * @throws AlgorandException 68 | */ 69 | public function build() : ApplicationCreateTransaction 70 | { 71 | parent::build(); 72 | 73 | // return ApplicationBaseTransaction::builder($this); 74 | return $this->applicationTransaction; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/Models/Transactions/Builders/ApplicationUpdateTransactionBuilder.php: -------------------------------------------------------------------------------- 1 | applicationTransaction = $applicationTransaction ?? new ApplicationUpdateTransaction(); 23 | $this->applicationTransaction->onCompletion = $onCompletion ?? OnCompletion::UPDATE_APPLICATION_OC(); 24 | parent::__construct($this->applicationTransaction, $this->applicationTransaction->onCompletion); 25 | } 26 | 27 | /** 28 | * Append and overwrite an existing transaction to this one. 29 | * 30 | * @param RawTransaction $transaction 31 | * @return $this 32 | * @throws AlgorandException 33 | */ 34 | public function append(RawTransaction $transaction): self 35 | { 36 | parent::append($transaction); 37 | if ($transaction instanceof ApplicationUpdateTransaction) { 38 | $this->approvalProgram($transaction->approvalProgram); 39 | $this->clearStateProgram($transaction->clearStateProgram); 40 | } 41 | 42 | return $this; 43 | } 44 | 45 | /** 46 | * Logic executed for every application transaction, except when on-completion is set to "clear". 47 | * It can read and write global state for the application, as well as account-specific local state. 48 | * Approval programs may reject the transaction. 49 | * 50 | * @param TEALProgram|null $approvalProgram 51 | * @return $this 52 | */ 53 | public function approvalProgram(?TEALProgram $approvalProgram): self 54 | { 55 | $this->applicationTransaction->approvalProgram = $approvalProgram; 56 | 57 | return $this; 58 | } 59 | 60 | /** 61 | * Logic executed for application transactions with on-completion set to "clear". 62 | * It can read and write global state for the application, as well as account-specific local state. 63 | * Clear state programs cannot reject the transaction. 64 | * 65 | * @param TEALProgram|null $clearStateProgram 66 | * @return $this 67 | */ 68 | public function clearStateProgram(?TEALProgram $clearStateProgram): self 69 | { 70 | $this->applicationTransaction->clearStateProgram = $clearStateProgram; 71 | 72 | return $this; 73 | } 74 | 75 | /** 76 | * @return ApplicationUpdateTransaction 77 | * @throws AlgorandException 78 | */ 79 | public function build() 80 | { 81 | parent::build(); 82 | 83 | return $this->applicationTransaction; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/Models/Transactions/Builders/AssetFreezeTransactionBuilder.php: -------------------------------------------------------------------------------- 1 | assetTransaction = new AssetFreezeTransaction(); 21 | parent::__construct(TransactionType::ASSET_FREEZE(), $this->assetTransaction); 22 | } 23 | 24 | /** 25 | * The ID of the asset being frozen or unfrozen. 26 | * 27 | * @param BigInteger|null $assetId 28 | * @return $this 29 | */ 30 | public function assetId(?BigInteger $assetId): self 31 | { 32 | $this->assetTransaction->assetId = $assetId; 33 | 34 | return $this; 35 | } 36 | 37 | /** 38 | * The address of the account whose asset is being frozen or unfrozen. 39 | * 40 | * @param Address|null $address 41 | * @return $this 42 | */ 43 | public function freezeTarget(?Address $address): self 44 | { 45 | $this->assetTransaction->freezeAddress = $address; 46 | 47 | return $this; 48 | } 49 | 50 | /** 51 | * True to freeze the asset. 52 | * 53 | * @param bool|null $freeze 54 | * @return $this 55 | */ 56 | public function freeze(?bool $freeze): self 57 | { 58 | $this->assetTransaction->freeze = $freeze; 59 | 60 | return $this; 61 | } 62 | 63 | /** 64 | * @return AssetFreezeTransaction 65 | * @throws AlgorandException 66 | */ 67 | public function build() 68 | { 69 | parent::build(); 70 | 71 | return $this->assetTransaction; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/Models/Transactions/Builders/KeyRegistrationTransactionBuilder.php: -------------------------------------------------------------------------------- 1 | keyRegTransacion = new KeyRegistrationTransaction(); 21 | parent::__construct(TransactionType::KEY_REGISTRATION(), $this->keyRegTransacion); 22 | } 23 | 24 | /** 25 | * The root participation public key. 26 | * 27 | * @param ParticipationPublicKey|null $votePublicKey 28 | * @return $this 29 | */ 30 | public function votePublicKey(?ParticipationPublicKey $votePublicKey): self 31 | { 32 | $this->keyRegTransacion->votePK = $votePublicKey; 33 | 34 | return $this; 35 | } 36 | 37 | /** 38 | * The VRF public key. 39 | * 40 | * @param VRFPublicKey|null $selectionPublicKey 41 | * @return $this 42 | */ 43 | public function selectionPublicKey(?VRFPublicKey $selectionPublicKey): self 44 | { 45 | $this->keyRegTransacion->selectionPK = $selectionPublicKey; 46 | 47 | return $this; 48 | } 49 | 50 | /** 51 | * The first round that the participation key is valid. 52 | * Not to be confused with the FirstValid round of the keyreg transaction. 53 | * 54 | * @param int|null $voteFirst 55 | * @return $this 56 | */ 57 | public function voteFirst(?int $voteFirst): self 58 | { 59 | $this->keyRegTransacion->voteFirst = $voteFirst; 60 | 61 | return $this; 62 | } 63 | 64 | /** 65 | * The last round that the participation key is valid. 66 | * Not to be confused with the LastValid round of the keyreg transaction. 67 | * 68 | * @param int|null $voteLast 69 | * @return $this 70 | */ 71 | public function voteLast(?int $voteLast): self 72 | { 73 | $this->keyRegTransacion->voteLast = $voteLast; 74 | 75 | return $this; 76 | } 77 | 78 | /** 79 | * This is the dilution for the 2-level participation key. 80 | * 81 | * @param int|null $dilution 82 | * @return $this 83 | */ 84 | public function voteKeyDilution(?int $dilution): self 85 | { 86 | $this->keyRegTransacion->voteKeyDilution = $dilution; 87 | 88 | return $this; 89 | } 90 | 91 | /** 92 | * @return KeyRegistrationTransaction 93 | * @throws AlgorandException 94 | */ 95 | public function build() 96 | { 97 | parent::build(); 98 | 99 | // TODO Fix the ugly builders 100 | return $this->keyRegTransacion; 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/Models/Transactions/Builders/PaymentTransactionBuilder.php: -------------------------------------------------------------------------------- 1 | paymentTransaction = new RawPaymentTransaction(); 26 | parent::__construct(TransactionType::PAYMENT(), $this->paymentTransaction); 27 | } 28 | 29 | /** 30 | * When set, it indicates that the transaction is requesting that the Sender account should be closed, and all 31 | * remaining funds, after the fee and amount are paid, be transferred to this address. 32 | * 33 | * @param Address|null $closeRemainderTo 34 | * @return $this 35 | */ 36 | public function closeRemainderTo(?Address $closeRemainderTo): self 37 | { 38 | $this->paymentTransaction->closeRemainderTo = $closeRemainderTo; 39 | 40 | return $this; 41 | } 42 | 43 | /** 44 | * The address of the account that receives the amount. 45 | * 46 | * @param Address|null $receiver 47 | * @return $this 48 | */ 49 | public function receiver(?Address $receiver): self 50 | { 51 | $this->paymentTransaction->receiver = $receiver; 52 | 53 | return $this; 54 | } 55 | 56 | /** 57 | * The total amount to be sent in microAlgos. 58 | * Amounts are returned in microAlgos - the base unit for Algos. 59 | * Micro denotes a unit x 10^-6. Therefore, 1 Algo equals 1,000,000 microAlgos. 60 | * 61 | * @param int|null $amount 62 | * @return $this 63 | */ 64 | public function amount(?int $amount): self 65 | { 66 | $this->paymentTransaction->amount = BigInteger::of($amount ?? 0); 67 | 68 | return $this; 69 | } 70 | 71 | /** 72 | * The total amount to be sent in microAlgos. 73 | * Amounts are returned in microAlgos - the base unit for Algos. 74 | * Micro denotes a unit x 10^-6. Therefore, 1 Algo equals 1,000,000 microAlgos. 75 | * 76 | * @param BigInteger $amount 77 | * @return $this 78 | */ 79 | public function bigAmount(BigInteger $amount): self 80 | { 81 | $this->paymentTransaction->amount = $amount; 82 | 83 | return $this; 84 | } 85 | 86 | /** 87 | * @return RawPaymentTransaction 88 | * @throws AlgorandException 89 | */ 90 | public function build() 91 | { 92 | parent::build(); 93 | 94 | return $this->paymentTransaction; 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/Models/Transactions/KeyRegistrationTransactionResponse.php: -------------------------------------------------------------------------------- 1 | localStateSchema; 47 | $fields['apgs'] = $this->globalStateSchema; 48 | $fields['apep'] = $this->extraPages; 49 | 50 | return $fields; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/Models/Transactions/Types/ApplicationUpdateTransaction.php: -------------------------------------------------------------------------------- 1 | approvalProgram) ? $this->approvalProgram->bytes() : null; 31 | $fields['apsu'] = isset($this->clearStateProgram) ? $this->clearStateProgram->bytes() : null; 32 | 33 | return $fields; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Models/Transactions/Types/AssetFreezeTransaction.php: -------------------------------------------------------------------------------- 1 | freezeAddress->address ?? null; 44 | $fields['faid'] = $this->assetId ? $this->assetId->toInt() : null; 45 | $fields['afrz'] = $this->freeze; 46 | 47 | return $fields; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/Models/Transactions/Types/AssetTransferTransaction.php: -------------------------------------------------------------------------------- 1 | assetId ? $this->assetId->toInt() : null; 59 | $fields['aamt'] = $this->amount ? $this->amount->toInt() : null; 60 | $fields['asnd'] = $this->assetSender->address ?? null; 61 | $fields['arcv'] = $this->receiver->address ?? null; 62 | $fields['aclose'] = $this->closeTo->address ?? null; 63 | 64 | return $fields; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/Models/Transactions/Types/KeyRegistrationTransaction.php: -------------------------------------------------------------------------------- 1 | votePK != null ? new Bin($this->votePK->getBytes()) : null; 53 | $fields['selkey'] = $this->selectionPK != null ? new Bin($this->selectionPK->getBytes()) : null; 54 | $fields['votefst'] = $this->voteFirst; 55 | $fields['votelst'] = $this->voteLast; 56 | $fields['votekd'] = $this->voteKeyDilution; 57 | 58 | return $fields; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/Models/Transactions/Types/RawPaymentTransaction.php: -------------------------------------------------------------------------------- 1 | isset($this->amount) ? $this->amount->toInt() : null, 39 | 'rcv' => isset($this->receiver) ? $this->receiver->address : null, 40 | 'close' => isset($this->closeRemainderTo) ? $this->closeRemainderTo->address : null, 41 | ]; 42 | 43 | return array_merge($fields, $paymentFields); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/Services/ManagesAccountsV2.php: -------------------------------------------------------------------------------- 1 | get($this->algodClient, "/v2/accounts/$address"); 79 | 80 | $info = new AccountInformation(); 81 | $this->jsonMapper->mapObject($response, $info); 82 | 83 | return $info; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/Services/ManagesBalanceV2.php: -------------------------------------------------------------------------------- 1 | get($this->algodClient, "/v2/accounts/$address"); 18 | 19 | $accountInformation = new AccountInformation(); 20 | $this->jsonMapper->mapObject($response, $accountInformation); 21 | 22 | return $accountInformation->amountWithoutPendingRewards; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Services/ManagesBlocksV2.php: -------------------------------------------------------------------------------- 1 | get($this->indexerClient, "/v2/blocks/$round"); 18 | 19 | $result = new BlockResult(); 20 | $this->jsonMapper->mapObject($response, $result); 21 | 22 | return $result; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Services/ManagesCatchupsV2.php: -------------------------------------------------------------------------------- 1 | post($this->algodClient, "/v2/catchup/$catchpoint"); 20 | 21 | $result = new CatchupResult(); 22 | $this->jsonMapper->mapObject($response, $result); 23 | 24 | return $result; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Services/ManagesLedgerV2.php: -------------------------------------------------------------------------------- 1 | get($this->algodClient, '/v2/ledger/supply'); 22 | 23 | $result = new LedgerSupplyResult(); 24 | $this->jsonMapper->mapObject($response, $result); 25 | 26 | return $result; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Services/ManagesNodesV2.php: -------------------------------------------------------------------------------- 1 | get($this->algodClient, '/genesis'); 20 | 21 | $genesis = new GenesisInformation(); 22 | $this->jsonMapper->mapObject($response, $genesis); 23 | 24 | return $genesis; 25 | } 26 | 27 | /** 28 | * Checks if the node is healthy. 29 | * 30 | * @return bool True if healthy. 31 | * @throws AlgorandException 32 | */ 33 | public function health() 34 | { 35 | $this->get($this->algodClient, '/health'); 36 | 37 | return true; 38 | } 39 | 40 | /** 41 | * Gets the current node status. 42 | * 43 | * @return \Rootsoft\Algorand\Models\NodeStatus The status of the Node. 44 | * @throws AlgorandException 45 | */ 46 | public function status() 47 | { 48 | $response = $this->get($this->algodClient, '/v2/status'); 49 | 50 | $status = new NodeStatus(); 51 | $this->jsonMapper->mapObject($response, $status); 52 | 53 | return $status; 54 | } 55 | 56 | /** 57 | * Gets the node status after waiting for the given round. 58 | * 59 | * Waits for a block to appear after round {round} and returns the node's status at the time. 60 | * 61 | * @param int $round The round to wait until returning status 62 | * @return \Rootsoft\Algorand\Models\NodeStatus The status of the Node. 63 | */ 64 | public function statusAfterRound(int $round) 65 | { 66 | $response = $this->get($this->algodClient, "/v2/status/wait-for-block-after/$round"); 67 | 68 | $status = new NodeStatus(); 69 | $this->jsonMapper->mapObject($response, $status); 70 | 71 | return $status; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/Services/ManagesTransactionParamsV2.php: -------------------------------------------------------------------------------- 1 | get($this->algodClient, '/v2/transactions/params'); 20 | 21 | $params = new TransactionParams(); 22 | $this->jsonMapper->mapObject($response, $params); 23 | 24 | return $params; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Templates/Parameters/AddressParameterValue.php: -------------------------------------------------------------------------------- 1 | address)); 13 | } 14 | 15 | public function placeholderSize(): int 16 | { 17 | return 32; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Templates/Parameters/BytesParameterValue.php: -------------------------------------------------------------------------------- 1 | offset = $offset; 18 | $this->value = $value; 19 | } 20 | 21 | /** 22 | * @return int 23 | */ 24 | public function getOffset(): int 25 | { 26 | return $this->offset; 27 | } 28 | 29 | /** 30 | * @return array 31 | */ 32 | public function toBytes(): array 33 | { 34 | return $this->value; 35 | } 36 | 37 | abstract public function placeholderSize(): int; 38 | } 39 | -------------------------------------------------------------------------------- /src/Traits/KeyPairGenerator.php: -------------------------------------------------------------------------------- 1 | getRawKeyMaterial(), 0, self::SEED_BYTES_LENGTH); 57 | 58 | return $seed; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/Utils/Algo.php: -------------------------------------------------------------------------------- 1 | 1, 21 | self::ALGOS => 1000000, 22 | ]; 23 | 24 | /** 25 | * Convert an amount of Algo's to the base unit of microAlgos. 26 | * 27 | * @param float $algo 28 | * @return int 29 | */ 30 | public static function toMicroAlgos(float $algo) 31 | { 32 | return $algo * self::$map[self::ALGOS]; 33 | } 34 | 35 | /** 36 | * Convert an amount of microAlgo's to Algos. 37 | * 38 | * @param float $microAlgos 39 | * @return int 40 | */ 41 | public static function fromMicroAlgos(float $microAlgos) 42 | { 43 | return $microAlgos / self::$map[self::ALGOS]; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/Utils/ArrayUtils.php: -------------------------------------------------------------------------------- 1 | packStr($value->) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Utils/Buffer.php: -------------------------------------------------------------------------------- 1 | getRawKeyMaterial() 55 | ); 56 | } 57 | 58 | public static function fillBytes(int $value, int $size = 32) 59 | { 60 | return array_fill(0, $size, $value); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/Utils/Encoder/BigIntEncoder.php: -------------------------------------------------------------------------------- 1 | MAX_UINT64 = BigInteger::fromBase('FFFFFFFFFFFFFFFF', 16); 27 | } 28 | 29 | return self::$instance; 30 | } 31 | 32 | /** 33 | * @throws AlgorandException 34 | */ 35 | public function encodeUint64($value): array 36 | { 37 | $value = $value instanceof BigInteger ? $value : BigInteger::of($value); 38 | if ($value->isLessThan(0) || $value->isGreaterThan($this->MAX_UINT64)) { 39 | throw new AlgorandException('Value cannot be represented by a uint64'); 40 | } 41 | 42 | $fixedLengthEncoding = CryptoUtils::fillBytes(0, 8); 43 | $encodedValue = Buffer::toArray($value->toBytes()); 44 | 45 | if (!empty($encodedValue) && $encodedValue[0] == 0) { 46 | // encodedValue is actually encoded as a signed 2's complement value, 47 | // so there may be a leading 0 for some encodings -- ignore it 48 | $encodedValue = array_slice($encodedValue, 1, count($encodedValue)); 49 | } 50 | 51 | $start = self::UINT64_LENGTH - count($encodedValue); 52 | $end = $start + count($encodedValue); 53 | 54 | array_splice($fixedLengthEncoding, $start, count($fixedLengthEncoding) - $start, $encodedValue); 55 | 56 | return $fixedLengthEncoding; 57 | } 58 | 59 | public function decodeUint64($data): BigInteger 60 | { 61 | $data = is_array($data) ? Buffer::toBinaryString($data) : $data; 62 | return BigInteger::fromBytes($data, false); 63 | } 64 | } -------------------------------------------------------------------------------- /src/Utils/Encoder/EncoderUtils.php: -------------------------------------------------------------------------------- 1 | append($baseTransaction) 21 | ->localStateSchema(EncoderUtils::toStateSchema($localStateSchema)) 22 | ->globalStateSchema(EncoderUtils::toStateSchema($globalStateSchema)) 23 | ->extraPages($extraPages) 24 | ->build(); 25 | } 26 | 27 | public function type(): string 28 | { 29 | return ApplicationCreateTransaction::class; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Utils/Transformers/ApplicationTransformer.php: -------------------------------------------------------------------------------- 1 | append($baseTransaction) 26 | ->applicationId(EncoderUtils::toBigInteger($applicationId)) 27 | ->onCompletion($onCompletion) 28 | ->arguments($arguments) 29 | ->accounts(array_map(fn(string $address) => Address::fromPublicKey($address), $accounts)) 30 | ->foreignApps($foreignApps) 31 | ->foreignAssets($foreignAssets) 32 | ->build(); 33 | } 34 | 35 | public function type(): string 36 | { 37 | return ApplicationBaseTransaction::class; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Utils/Transformers/ApplicationUpdateTransformer.php: -------------------------------------------------------------------------------- 1 | append($baseTransaction) 20 | ->approvalProgram(EncoderUtils::toTEALProgram($approvalProgram)) 21 | ->clearStateProgram(EncoderUtils::toTEALProgram($clearStateProgram)) 22 | ->build(); 23 | } 24 | 25 | public function type(): string 26 | { 27 | return ApplicationUpdateTransaction::class; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Utils/Transformers/AssetConfigTransformer.php: -------------------------------------------------------------------------------- 1 | append($baseTransaction) 31 | ->assetId(EncoderUtils::toBigInteger($assetId)) 32 | ->totalAssetsToCreate(EncoderUtils::toBigInteger($total)) 33 | ->decimals($decimals) 34 | ->defaultFrozen($defaultFrozen) 35 | ->unitName($unitName) 36 | ->assetName($assetName) 37 | ->url($url) 38 | ->metadata($metadata) 39 | ->managerAddress(EncoderUtils::toAddress($managerAddress)) 40 | ->reserveAddress(EncoderUtils::toAddress($reserveAddress)) 41 | ->freezeAddress(EncoderUtils::toAddress($freezeAddress)) 42 | ->clawbackAddress(EncoderUtils::toAddress($clawbackAddress)) 43 | ->build(); 44 | } 45 | 46 | public function type(): string 47 | { 48 | return AssetConfigTransaction::class; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/Utils/Transformers/AssetFreezeTransformer.php: -------------------------------------------------------------------------------- 1 | append($baseTransaction) 21 | ->assetId(EncoderUtils::toBigInteger($assetId)) 22 | ->freezeTarget(EncoderUtils::toAddress($freezeAddress)) 23 | ->freeze($freeze) 24 | ->build(); 25 | } 26 | 27 | public function type(): string 28 | { 29 | return AssetFreezeTransaction::class; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Utils/Transformers/AssetTransferTransformer.php: -------------------------------------------------------------------------------- 1 | append($baseTransaction) 23 | ->assetId(EncoderUtils::toBigInteger($assetId)) 24 | ->amount($amount) 25 | ->assetSender(EncoderUtils::toAddress($assetSender)) 26 | ->assetReceiver(EncoderUtils::toAddress($assetReceiver)) 27 | ->assetCloseTo(EncoderUtils::toAddress($assetCloseTo)) 28 | ->build(); 29 | } 30 | 31 | public function type(): string 32 | { 33 | return AssetTransferTransaction::class; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Utils/Transformers/BaseTransactionTransformer.php: -------------------------------------------------------------------------------- 1 | type(ArrayUtils::findValueOrNull($value, 'type')) 19 | ->flatFee(ArrayUtils::findValueOrNull($value, 'fee')) 20 | ->firstValid(ArrayUtils::findValueOrNull($value, 'fv')) 21 | ->lastValid(ArrayUtils::findValueOrNull($value, 'lv')) 22 | ->note(ArrayUtils::findValueOrNull($value, 'note')) 23 | ->sender($sender != null ? Address::fromPublicKey($sender) : null) 24 | ->genesisId(ArrayUtils::findValueOrNull($value, 'gen')) 25 | ->genesisHash(ArrayUtils::findValueOrNull($value, 'gh')) 26 | ->lease(ArrayUtils::findValueOrNull($value, 'lx')) 27 | ->group(ArrayUtils::findValueOrNull($value, 'grp')) 28 | ->rekeyTo($rekeyTo != null ? Address::fromPublicKey($rekeyTo) : null) 29 | ->build(); 30 | } 31 | 32 | public function type(): string 33 | { 34 | return RawTransaction::class; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/Utils/Transformers/KeyRegistrationTransformer.php: -------------------------------------------------------------------------------- 1 | append($baseTransaction) 23 | ->votePublicKey(EncoderUtils::toParticipationPublicKey($votePK)) 24 | ->selectionPublicKey(EncoderUtils::toVRFPublicKey($selectionPK)) 25 | ->voteFirst($voteFirst) 26 | ->voteLast($voteLast) 27 | ->voteKeyDilution($voteKeyDilution) 28 | ->build(); 29 | } 30 | 31 | public function type(): string 32 | { 33 | return KeyRegistrationTransaction::class; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Utils/Transformers/LogicSignatureTransformer.php: -------------------------------------------------------------------------------- 1 | transform($className, $value); 21 | 22 | return TransactionBuilder::payment() 23 | ->append($baseTransaction) 24 | ->amount($amount) 25 | ->receiver($receiver ? Address::fromPublicKey($receiver) : null) 26 | ->closeRemainderTo($closeRemainderTo ? Address::fromPublicKey($closeRemainderTo) : null) 27 | ->build(); 28 | } 29 | 30 | public function type(): string 31 | { 32 | return RawPaymentTransaction::class; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Utils/Transformers/TransformerFactory.php: -------------------------------------------------------------------------------- 1 | unpacker = $unpacker ?? new BufferUnpacker(); 24 | $this->transformers = []; 25 | } 26 | 27 | /** 28 | * Register a new transformer. 29 | * @param MessagePackTransformer $transformer 30 | */ 31 | public function registerTransformer(MessagePackTransformer $transformer) 32 | { 33 | $this->transformers[$transformer->type()] = $transformer; 34 | } 35 | 36 | /** 37 | * Find the transformer for the class name. 38 | * 39 | * @param string $className 40 | * @return MessagePackTransformer 41 | */ 42 | public function findTransformer(string $className): MessagePackTransformer 43 | { 44 | return $this->transformers[$className]; 45 | } 46 | 47 | /** 48 | * Transform and unpack the binary data. 49 | * @param string $data 50 | * @param string $className 51 | * @return mixed 52 | */ 53 | public function transform(string $data, string $className) 54 | { 55 | // Find the transformer for the class name 56 | $transformer = $this->transformers[$className]; 57 | 58 | // Unpack the messagepack 59 | $this->unpacker->reset($data); 60 | $value = $this->unpacker->unpack(); 61 | 62 | // Unpack the messagepack 63 | return $transformer->transform($className, $value); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/config/algorand.php: -------------------------------------------------------------------------------- 1 | [ 22 | 'api_url' => 'https://testnet.algoexplorerapi.io', 23 | 'api_key' => '', 24 | 'api_token_header' => 'X-Algo-API-Token', 25 | ], 26 | 27 | /* 28 | |-------------------------------------------------------------------------- 29 | | Indexer Credentials 30 | |-------------------------------------------------------------------------- 31 | | 32 | | The credentials used to communicate with the Indexer daemon. 33 | | As default, the credentials are used for the TestNet hosted by AlgoExplorer. 34 | | PureStake API Token header: X-API-Key 35 | | Algorand API Token header: X-Indexer-API-Token 36 | | 37 | | For more information see: 38 | | * https://developer.algorand.org/docs/build-apps/setup/ 39 | | * https://testnet.algoexplorer.io/api-dev/indexer-v2 40 | | * https://www.purestake.com/technology/algorand-api/ 41 | | 42 | */ 43 | 'indexer' => [ 44 | 'api_url' => 'https://testnet.algoexplorerapi.io/idx2', 45 | 'api_key' => '', 46 | 'api_token_header' => 'X-Indexer-API-Token', 47 | ], 48 | 49 | /* 50 | |-------------------------------------------------------------------------- 51 | | KMD Credentials 52 | |-------------------------------------------------------------------------- 53 | | 54 | | The credentials used to communicate with the KMD daemon. 55 | | As default, localhost is used. 56 | | If you are using a third-party API service, this process likely will not be available to you. 57 | | 58 | | For more information see: 59 | | * https://developer.algorand.org/docs/build-apps/setup/ 60 | | * https://developer.algorand.org/docs/features/accounts/create/#wallet-derived-kmd 61 | | 62 | */ 63 | 'kmd' => [ 64 | 'api_url' => '127.0.0.1', 65 | 'api_key' => '', 66 | 'api_token_header' => 'X-KMD-API-Token', 67 | ], 68 | 69 | ]; 70 | -------------------------------------------------------------------------------- /tests/Feature/AlgorandTest.php: -------------------------------------------------------------------------------- 1 | assertEquals($seedphrase->words, explode(' ', $expectedWords)); 24 | 25 | // Seed 26 | $seed = Mnemonic::Words($seedphrase->words); 27 | $this->assertEquals(hex2bin($seed->entropy), $zeroKeys); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /tests/TestCase.php: -------------------------------------------------------------------------------- 1 | encodedAddress); 23 | $this->assertEquals($address, $address2); 24 | } 25 | } 26 | 27 | public function testGoldenValues() 28 | { 29 | $golden = '7777777777777777777777777777777777777777777777777774MSJUVU'; 30 | $b = Buffer::toBinaryString(CryptoUtils::fillBytes(0xFF)); 31 | $address = Address::fromPublicKey($b); 32 | $this->assertEquals($address->encodedAddress, $golden); 33 | } 34 | 35 | public function testAddressForApplication() 36 | { 37 | $applicationId = 77; 38 | $actual = Address::forApplication($applicationId); 39 | $expected = Address::fromAlgorandAddress('PCYUFPA2ZTOYWTP43MX2MOX2OWAIAXUDNC2WFCXAGMRUZ3DYD6BWFDL5YM'); 40 | $this->assertEquals($expected->encodedAddress, $actual->encodedAddress); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /tests/Unit/Crypto/MultiSigAddressTest.php: -------------------------------------------------------------------------------- 1 | new Ed25519PublicKey($value->address), [$one, $two, $three]); 24 | $msigAddr = new MultiSignatureAddress(1, 2, $publicKeys); 25 | 26 | $this->assertEquals($msigAddr->toString(), 'UCE2U2JC4O4ZR6W763GUQCG57HQCDZEUJY4J5I6VYY4HQZUJDF7AKZO5GM'); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /tests/Unit/Teal/TealSignTest.php: -------------------------------------------------------------------------------- 1 | sign($account, $data); 28 | $sig2 = $program->sign($account, $data); 29 | $this->assertEquals($sig1, $sig2); 30 | 31 | $buffer = utf8_encode(TEALProgram::PROGDATA_SIGN_PREFIX); 32 | $buffer .= $address->address; 33 | $buffer .= $data; 34 | 35 | $verified = CryptoUtils::verify($buffer, $sig1->bytes(), $account->getPublicKey()); 36 | $this->assertTrue($verified); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /tests/Unit/Templates/HashTimeLockContractTest.php: -------------------------------------------------------------------------------- 1 | assertEquals($result->getValue(), $a); 24 | //$this->assertEquals($result->getValue(), $a); 25 | } 26 | 27 | public function testHashTimeLockContract() 28 | { 29 | $goldenAddress = 'FBZIR3RWVT2BTGVOG25H3VAOLVD54RTCRNRLQCCJJO6SVSCT5IVDYKNCSU'; 30 | $goldenProgram = 'ASAE6AcBAMDPJCYDIOaalh5vLV96yGYHkmVSvpgjXtMzY8qIkYu5yTipFbb5IBB2YRNPIfx8AiI9UKues2ALw//DcSQjoeR7sfmp2/VfIP68oLsUSlpOp7Q4pGgayA5soQW8tgf8VlMlyVaV9qITMQEiDjEQIxIQMQcyAxIQMQgkEhAxCSgSLQEpEhAxCSoSMQIlDRAREA=='; 31 | $goldenTx = 'gqRsc2lngqNhcmeRxAhwcmVpbWFnZaFsxJcBIAToBwEAwM8kJgMg5pqWHm8tX3rIZgeSZVK+mCNe0zNjyoiRi7nJOKkVtvkgEHZhE08h/HwCIj1Qq56zYAvD/8NxJCOh5Hux+anb9V8g/ryguxRKWk6ntDikaBrIDmyhBby2B/xWUyXJVpX2ohMxASIOMRAjEhAxBzIDEhAxCCQSEDEJKBItASkSEDEJKhIxAiUNEBEQo3R4boelY2xvc2XEIOaalh5vLV96yGYHkmVSvpgjXtMzY8qIkYu5yTipFbb5o2ZlZc0D6KJmdgGiZ2jEIH+DsWV/8fxTuS3BgUih1l38LUsfo9Z3KErd0gASbZBpomx2ZKNzbmTEIChyiO42rPQZmq42un3UDl1H3kZii2K4CElLvSrIU+oqpHR5cGWjcGF5'; 32 | 33 | $owner = Address::fromAlgorandAddress('726KBOYUJJNE5J5UHCSGQGWIBZWKCBN4WYD7YVSTEXEVNFPWUIJ7TAEOPM'); 34 | $receiver = Address::fromAlgorandAddress('42NJMHTPFVPXVSDGA6JGKUV6TARV5UZTMPFIREMLXHETRKIVW34QFSDFRE'); 35 | $image = 'EHZhE08h/HwCIj1Qq56zYAvD/8NxJCOh5Hux+anb9V8='; 36 | 37 | // Create the contract 38 | $contract = HashTimeLockContract::create($owner, $receiver, 1, $image, 600000, 1000); 39 | 40 | $this->assertEquals($contract->getAddress()->encodedAddress, $goldenAddress); 41 | $this->assertEquals($contract->getProgram(), Base64::decode($goldenProgram)); 42 | 43 | // Create the transactions 44 | $preImageAsBase64 = 'cHJlaW1hZ2U='; 45 | $gh = 'f4OxZX/x/FO5LcGBSKHWXfwtSx+j1ncoSt3SABJtkGk='; 46 | 47 | $signedTx = HashTimeLockContract::getTransaction($contract, $preImageAsBase64, 1, 100, $gh, 0); 48 | 49 | $this->assertEquals($signedTx->toBase64(), $goldenTx); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /tests/Unit/Templates/LimitOrderTest.php: -------------------------------------------------------------------------------- 1 | assertEquals($contract->getAddress()->encodedAddress, $goldenAddress); 29 | $this->assertEquals($contract->getProgram(), Base64::decode($goldenProgram)); 30 | 31 | // Sign the contract 32 | $privateKey1 = Base64::decode('DTKVj7KMON3GSWBwMX9McQHtaDDi8SDEBi0bt4rOxlHNRahLa0zVG+25BDIaHB1dSoIHIsUQ8FFcdnCdKoG+Bg=='); 33 | $sender = Account::seed(substr($privateKey1, 0, 32)); 34 | 35 | // Get the swap transactions 36 | $genesisHash = 'f4OxZX/x/FO5LcGBSKHWXfwtSx+j1ncoSt3SABJtkGk='; 37 | $transactions = LimitOrder::getSwapAssetsTransaction($contract, $sender, 3000, 10000, 1234, 2234, $genesisHash, 10); 38 | 39 | $goldenTx1 = 'gqRsc2lngaFsxLcBIAoAAcCWsQICkE4EuWBkHsDEByYBIP68oLsUSlpOp7Q4pGgayA5soQW8tgf8VlMlyVaV9qITMRYiEjEQIxIQMQEkDhAyBCMSQABVMgQlEjEIIQQNEDEJMgMSEDMBECEFEhAzAREhBhIQMwEUKBIQMwETMgMSEDMBEiEHHTUCNQExCCEIHTUENQM0ATQDDUAAJDQBNAMSNAI0BA8QQAAWADEJKBIxAiEJDRAxBzIDEhAxCCISEBCjdHhuiaNhbXTNJxCjZmVlzQisomZ2zQTSomdoxCB/g7Flf/H8U7ktwYFIodZd/C1LH6PWdyhK3dIAEm2QaaNncnDEIKz368WOGpdE/Ww0L8wUu5Ly2u2bpG3ZSMKCJvcvGApTomx2zQi6o3JjdsQgzUWoS2tM1RvtuQQyGhwdXUqCByLFEPBRXHZwnSqBvgajc25kxCBd4Wnq60VaWXeVmuPt0x1XgMQSyP4nUnlh5G2Rhyo+taR0eXBlo3BheQ=='; 40 | $goldenTx2 = 'gqNzaWfEQKXv8Z6OUDNmiZ5phpoQJHmfKyBal4gBZLPYsByYnlXCAlXMBeVFG5CLP1k5L6BPyEG2/XIbjbyM0CGG55CxxAKjdHhuiqRhYW10zQu4pGFyY3bEIP68oLsUSlpOp7Q4pGgayA5soQW8tgf8VlMlyVaV9qITo2ZlZc0JJKJmds0E0qJnaMQgf4OxZX/x/FO5LcGBSKHWXfwtSx+j1ncoSt3SABJtkGmjZ3JwxCCs9+vFjhqXRP1sNC/MFLuS8trtm6Rt2UjCgib3LxgKU6Jsds0IuqNzbmTEIM1FqEtrTNUb7bkEMhocHV1KggcixRDwUVx2cJ0qgb4GpHR5cGWlYXhmZXKkeGFpZM0wOQ=='; 41 | 42 | $this->assertEquals($transactions, Base64::decode($goldenTx1).Base64::decode($goldenTx2)); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /tests/Unit/Templates/PeriodicPaymentTest.php: -------------------------------------------------------------------------------- 1 | assertEquals($contract->getAddress()->encodedAddress, $goldenAddress); 30 | $this->assertEquals($contract->getProgram(), Base64::decode($goldenProgram)); 31 | 32 | // Get the withdrawal transaction 33 | $gh = 'f4OxZX/x/FO5LcGBSKHWXfwtSx+j1ncoSt3SABJtkGk='; 34 | $signedTx = PeriodicPayment::getWithdrawalTransaction($contract, 1200, $gh, 0); 35 | $this->assertEquals($signedTx->toBase64(), $goldenTx); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /tests/Unit/Templates/SplitTest.php: -------------------------------------------------------------------------------- 1 | assertEquals($contract->getAddress()->encodedAddress, $goldenAddress); 36 | $this->assertEquals($contract->getProgram(), Base64::decode($goldenProgram)); 37 | 38 | // Get the transactions 39 | $gh = 'f4OxZX/x/FO5LcGBSKHWXfwtSx+j1ncoSt3SABJtkGk='; 40 | $transactions = Split::getTransactions($contract, $minPay * ($rat1 + $rat2), 1, 100, $gh, 10000); 41 | 42 | $this->assertEquals(Base64::encode($transactions), $goldenTx); 43 | } 44 | } 45 | --------------------------------------------------------------------------------