├── distributed-worker ├── .gitignore ├── composer.json ├── setup.php ├── 90-reclaim-escrow.php ├── common.php ├── 40-customer-uses.php ├── README.md ├── 30-customer-verifies.php ├── 20-worker-generates.php ├── 10-customer-requests.php └── composer.lock ├── README.md └── LICENSE /distributed-worker/.gitignore: -------------------------------------------------------------------------------- 1 | vendor/ 2 | -------------------------------------------------------------------------------- /distributed-worker/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "require": { 3 | "zulucrypto/stellar-api": "^0.3.0" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /distributed-worker/setup.php: -------------------------------------------------------------------------------- 1 | fundAccount($workerKeypair); 10 | $stellarNetwork->fundAccount($customerKeypair); 11 | 12 | print "Worker : " . $workerKeypair->getPublicKey() . PHP_EOL; 13 | print "Customer: " . $customerKeypair->getPublicKey() . PHP_EOL; 14 | print "Escrow : " . $escrowKeypair->getPublicKey() . PHP_EOL; 15 | print "Vanity : " . $vanityKeypair->getPublicKey() . PHP_EOL; -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Stellar Smart Contract Examples 2 | 3 | *Note: Stellar smart contracts are much different from Ethereum smart contracts. 4 | They are NOT turing complete and are implemented as an agreement between 5 | multiple parties and enforced by transactions.* 6 | 7 | ## Blog Posts / Web Resources 8 | 9 | * [Multisig and Simple Contracts on Stellar](https://www.stellar.org/blog/multisig-and-simple-contracts-stellar/) 10 | * [NodeJS Examples](https://github.com/chatch/stellar-contracts) 11 | 12 | ## Complex Examples 13 | 14 | * [Distributed Workers: Generating a vanity keypair](distributed-worker/README.md) 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /distributed-worker/90-reclaim-escrow.php: -------------------------------------------------------------------------------- 1 | buildTransaction($escrowKeypair) 14 | // Must clean up data to be able to merge account 15 | ->setAccountData('request:generateVanityAddress') 16 | ->addMergeOperation($customerKeypair) 17 | ->submit(); -------------------------------------------------------------------------------- /distributed-worker/common.php: -------------------------------------------------------------------------------- 1 | vanity..."; 20 | $stellarNetwork->buildTransaction($customerKeypair) 21 | ->addLumenPayment($vanityKeypair, 10.00001) // includes fee for return transaction 22 | ->submit($customerKeypair); 23 | print "DONE" . PHP_EOL; 24 | 25 | 26 | 27 | // Send XLM back from the vanity account 28 | // NOTE: signer on this is still $customerKeypair 29 | print "[2 of 2] Returning XLM to customer..."; 30 | $stellarNetwork->buildTransaction($vanityKeypair) 31 | ->addLumenPayment($customerKeypair, 10) 32 | ->submit($customerKeypair); 33 | print "DONE" . PHP_EOL; -------------------------------------------------------------------------------- /distributed-worker/README.md: -------------------------------------------------------------------------------- 1 | ## Description 2 | 3 | Demonstrates how to build a smart contract between a Customer and a Worker to 4 | generate a vanity keypair 5 | 6 | 7 | ## Details 8 | 9 | A Medium post describing this smart contract is available at: https://medium.com/@zulucrypto_23845/distributed-trustless-workers-with-stellar-e197fd1b77f6 10 | 11 | See the "Code Setup" section if you'd like to try out this smart contract. 12 | 13 | ## Setup 14 | 15 | **Install dependencies with composer** 16 | 17 | ```bash 18 | $ cd distributed-worker/ 19 | $ composer install 20 | ``` 21 | 22 | 23 | **Generate Keypairs** 24 | 25 | To run this example on the test network, you will need to edit `common.php` and 26 | generate new keypairs for all of the testing accounts. 27 | 28 | One easy way to do this is to change the "passphrase" used in the call to `Keypair::newFromMnemonic`: 29 | 30 | ```php 31 | $workerKeypair = Keypair::newFromMnemonic('...', 'CUSTOM_TEXT_HERE'); 32 | ``` 33 | 34 | **Fund accounts** 35 | 36 | Run `setup.php` to fund demo accounts: 37 | 38 | ```bash 39 | $ php setup.php 40 | ``` 41 | 42 | **Start executing the contract** 43 | 44 | Start by looking at the code in `10-customer-requests.php` and by running it: 45 | 46 | ```bash 47 | $ cd distributed-worker/ 48 | $ php 10-customer-requests.php 49 | ``` 50 | -------------------------------------------------------------------------------- /distributed-worker/30-customer-verifies.php: -------------------------------------------------------------------------------- 1 | getAccount($workerKeypair->getPublicKey()); 24 | 25 | $accountData = $workerAccount->getData(); 26 | 27 | // If the customer keypair doesn't show up, the worker hasn't discovered the request yet 28 | if (!isset($accountData[$customerKeypair->getPublicKey()])) { 29 | die("Worker has not started generating the vanity address"); 30 | } 31 | 32 | // Worker has started work on generating the vanity keypair 33 | if ($accountData[$customerKeypair->getPublicKey()] == "PROCESSING") { 34 | die("Worker has not generated the vanity keypair yet"); 35 | } 36 | 37 | // At this point, the worker is finished and we can read the data we'll need for 38 | // closing the transaction by paying the worker and receiving the vanity account 39 | $vanityPublicKey = $accountData[$customerKeypair->getPublicKey()]; 40 | $workerProofSignature = $accountData[$customerKeypair->getPublicKey() . '_proof']; 41 | $workerTransactionSignature = $accountData[$customerKeypair->getPublicKey() . '_sigW']; 42 | $vanityTransactionSignature = $accountData[$customerKeypair->getPublicKey() . '_sigV']; 43 | 44 | print "Worker found vanity key: " . $vanityPublicKey . PHP_EOL; 45 | 46 | // Verify that the signature is valid by checking that the worker was able to sign 47 | // a message with the private key of the vanity keypair 48 | $verificationKeypair = Keypair::newFromPublicKey($vanityPublicKey); 49 | 50 | $isValid = $verificationKeypair->verifySignature($workerProofSignature, 'vanity address confirmation'); 51 | 52 | if ($isValid) { 53 | print "Signature valid: worker has the private key for $vanityPublicKey" . PHP_EOL; 54 | } 55 | else { 56 | die("Invalid signature, cannot confirm $vanityPublicKey"); 57 | } 58 | 59 | /* 60 | * Everything checks out, so now it's time to submit the finalizing transaction 61 | * to the network. 62 | * 63 | * This transaction: 64 | * 65 | * 1. Clears out account data (cannot merge an account that has data values) 66 | * 2. Merges the escrow account into the worker account (paying for the key) 67 | * 3. Vanity account: Adds the customer's account as a signer with weight 1 68 | * 4. Vanity account: Sets all thresholds to 1 69 | * 5. Vanity account: Sets the master weight to 0 (now it cannot be used by the worker) 70 | * 71 | * This transaction will require two signatures (one by the customer and one by 72 | * the worker). The worker has already published their signature as a data value, 73 | * so it's up to the customer to generate a signature and submit to the network. 74 | */ 75 | 76 | // Generate transaction 77 | $signerKey = SignerKey::fromKeypair($customerKeypair); 78 | $signer = new Signer($signerKey, 1); 79 | 80 | // NOTE: source account on this operation is the vanity keypair account. 81 | // The source account for all other operations is the escrow keypair 82 | $op = new SetOptionsOp($vanityPublicKey); 83 | $op->updateSigner($signer); 84 | $op->setMasterWeight(0); 85 | $op->setLowThreshold(1); 86 | $op->setMediumThreshold(1); 87 | $op->setHighThreshold(1); 88 | 89 | // NOTE: this transaction must exactly match the one built in 20-worker-generates.php 90 | $finalizeTx = $stellarNetwork->buildTransaction($customerKeypair) 91 | // Must be cleared to merge account 92 | ->clearAccountData('request:generateVanityAddress', $escrowKeypair) 93 | ->addOperation($op) 94 | ->addMergeOperation($workerKeypair, $escrowKeypair) 95 | ->sign($customerKeypair); 96 | 97 | // Add the signature from the worker that we read from the data value on their 98 | // account. We need the worker's public key for calculating the signature's hint 99 | $finalizeTx->addRawSignature($workerTransactionSignature, Keypair::newFromPublicKey($workerKeypair->getPublicKey())); 100 | 101 | // Add the signature for the vanity keypair since it's required by the operation 102 | // that adds the customer as a signer and updates the weights 103 | $finalizeTx->addRawSignature($vanityTransactionSignature, Keypair::newFromPublicKey($vanityPublicKey)); 104 | 105 | print "Submitting transfer transaction..."; 106 | $stellarNetwork->submitB64Transaction($finalizeTx->toBase64()); 107 | print "DONE" . PHP_EOL; -------------------------------------------------------------------------------- /distributed-worker/20-worker-generates.php: -------------------------------------------------------------------------------- 1 | buildTransaction($workerKeypair) 32 | // ->setAccountData($customerKeypair->getPublicKey(), 'PROCESSING') 33 | // ->submit($workerKeypair); 34 | 35 | 36 | // ---------------------------------------------------- 37 | // todo: in a real implementation, this is where the processing would happen 38 | // Since this is just a demo, we already have the key generated and stored 39 | // in $vanityKeypair 40 | print "[SIMULATED] Found vanity keypair: " . $vanityKeypair->getPublicKey() . PHP_EOL; 41 | 42 | 43 | // After the account is discovered, fund it with the minimum balance 44 | // min balance + 1 extra signer (customer) 45 | $newAccountMinBalance = 1 + 0.5; 46 | 47 | // Fund the vanity keypair so we can add the customer as a signer 48 | if (!$stellarNetwork->getAccount($vanityKeypair)) { 49 | print "Funding vanity keypair from " . $workerKeypair->getPublicKey() . " "; 50 | $stellarNetwork->buildTransaction($workerKeypair) 51 | ->addCreateAccountOp($vanityKeypair, $newAccountMinBalance) 52 | ->submit($workerKeypair); 53 | print "DONE" . PHP_EOL; 54 | } 55 | 56 | // ---------------------------------------------------- 57 | /* 58 | * Once the keypair has been found, we need to let the customer see it as well 59 | * as prove that we really know the secret key and didn't just make up a public 60 | * key. 61 | */ 62 | 63 | // Showing the generated keypair to the customer is as easy as updating the 64 | // key/value pair 65 | 66 | $stellarNetwork->buildTransaction($workerKeypair) 67 | ->setAccountData($customerKeypair->getPublicKey(), $vanityKeypair->getPublicKey()) 68 | ->submit($workerKeypair); 69 | 70 | // Proving that we have the secret key is a matter of signing something with it 71 | // so that the customer can verify we actually control it. In this case, we'll 72 | // just sign the string "vanity address confirmation" 73 | 74 | $message = "vanity address confirmation"; 75 | $signature = $vanityKeypair->sign($message); 76 | 77 | // Write this to the blockchain as well so it can be verified 78 | $stellarNetwork->buildTransaction($workerKeypair) 79 | ->setAccountData($customerKeypair->getPublicKey() . "_proof", $signature) 80 | ->submit($workerKeypair); 81 | 82 | 83 | // Finally, generate the transaction that will be used to transfer the vanity 84 | // address and pay the worker 85 | $signerKey = SignerKey::fromKeypair($customerKeypair); 86 | $signer = new Signer($signerKey, 1); 87 | 88 | // NOTE: source account on this operation is the vanity keypair account. 89 | // The source account for all other operations is the escrow keypair 90 | $op = new SetOptionsOp($vanityKeypair); 91 | $op->updateSigner($signer); 92 | $op->setMasterWeight(0); 93 | $op->setLowThreshold(1); 94 | $op->setMediumThreshold(1); 95 | $op->setHighThreshold(1); 96 | 97 | // NOTE: this transaction must exactly match the one built in 30-customer-verifies.php 98 | $finalizeTx = $stellarNetwork->buildTransaction($customerKeypair) 99 | // Must be cleared to merge account 100 | ->clearAccountData('request:generateVanityAddress', $escrowKeypair) 101 | ->addOperation($op) 102 | ->addMergeOperation($workerKeypair, $escrowKeypair); 103 | 104 | // Publish the worker's signature for this transaction 105 | $stellarNetwork->buildTransaction($workerKeypair) 106 | ->setAccountData($customerKeypair->getPublicKey() . "_sigW", $finalizeTx->getSignatureForKeypair($workerKeypair)->getRawSignature()) 107 | ->submit($workerKeypair); 108 | 109 | // Publish the vanity account's signature (required for updating its signers) 110 | $stellarNetwork->buildTransaction($workerKeypair) 111 | ->setAccountData($customerKeypair->getPublicKey() . "_sigV", $finalizeTx->getSignatureForKeypair($vanityKeypair)->getRawSignature()) 112 | ->submit($workerKeypair); 113 | 114 | 115 | // See 30-customer-verifies.php for how the customer verifies the proof, constructs 116 | // the same transaction, adds their signature, and submits 117 | 118 | print "Worker Account: " . $workerKeypair->getPublicKey() . PHP_EOL; 119 | print "Updated Worker account with proof of keypair" . PHP_EOL; -------------------------------------------------------------------------------- /distributed-worker/10-customer-requests.php: -------------------------------------------------------------------------------- 1 | getAccount($escrowKeypair)) { 23 | $stellarNetwork->buildTransaction($customerKeypair) 24 | ->addCreateAccountOp($escrowKeypair, 100.00006) // 100 XLM after setup fees + transfer transaction 25 | ->submit($customerKeypair); 26 | } 27 | 28 | print "Created escrow account: " . $escrowKeypair->getPublicKey() . PHP_EOL; 29 | 30 | /* 31 | * In order to make this an escrow account, we need to prove to the worker that 32 | * no one is able to withdraw funds from it while the worker is searching for 33 | * a vanity address. 34 | * 35 | * This is accomplished by: 36 | * - Making the worker and customer signers of equal weight (1) 37 | * - Requiring both signers to agree on any transaction (thresholds are set to 2) 38 | * 39 | * However, we also need to handle the case where no worker takes the job and we 40 | * need to reclaim the account. This can be done by adding a preauthorized merge 41 | * transaction that's not valid until 30 days from now. 42 | * 43 | * This allows the worker to know that the funds are guaranteed to be available 44 | * for 30 days. 45 | */ 46 | 47 | // Load up the escrow account 48 | $account = $stellarNetwork->getAccount($escrowKeypair); 49 | 50 | // Precalculate some sequence numbers since they're necessary for transactions 51 | $startingSequenceNumber = $account->getSequence(); 52 | // Track how many transactions are necessary to set up the escrow account 53 | // We need this so we can correctly calculate the "reclaim account" sequence number 54 | $numSetupTransactions = 5; 55 | 56 | $reclaimAccountOrPaySeqNum = $startingSequenceNumber + $numSetupTransactions + 1; 57 | 58 | // Update the account with a data value indicating what vanity address to search for 59 | print "Adding data entry to request a vanity address..."; 60 | $stellarNetwork->buildTransaction($escrowKeypair) 61 | ->setAccountData('request:generateVanityAddress', 'G*ZULU') 62 | ->submit($escrowKeypair); 63 | print "DONE" . PHP_EOL; 64 | 65 | // Fallback transaction: reclaim the escrow account if no workers generate the 66 | // vanity address in 30 days 67 | $reclaimTx = $stellarNetwork->buildTransaction($escrowKeypair) 68 | ->setSequenceNumber(new BigInteger($reclaimAccountOrPaySeqNum)) 69 | // todo: uncomment this out in a real implementation 70 | //->setLowerTimebound(new \DateTime('+30 days')) 71 | ->setAccountData('request:generateVanityAddress') 72 | ->addMergeOperation($customerKeypair) 73 | ->getTransactionEnvelope(); 74 | 75 | // Add hash of $reclaimTx as a signer on the account 76 | // See: https://www.stellar.org/developers/guides/concepts/multi-sig.html#pre-authorized-transaction 77 | $txHashSigner = new Signer( 78 | SignerKey::fromPreauthorizedHash($reclaimTx->getHash()), 79 | 2 // weight must be enough so no other signers are needed 80 | ); 81 | $addReclaimTxSignerOp = new SetOptionsOp(); 82 | $addReclaimTxSignerOp->updateSigner($txHashSigner); 83 | 84 | print "Adding pre-authorized reclaim transaction as a signer... "; 85 | $stellarNetwork->buildTransaction($escrowKeypair) 86 | ->addOperation($addReclaimTxSignerOp) 87 | ->submit($escrowKeypair); 88 | print "DONE" . PHP_EOL; 89 | 90 | print "Added pre-auth reclaim transaction valid at sequence " . $reclaimAccountOrPaySeqNum . PHP_EOL; 91 | print "To reclaim the escrow account, run 90-reclaim-escrow.php" . PHP_EOL; 92 | 93 | // Add worker account as a signer of weight 1 94 | $workerSigner = new Signer( 95 | SignerKey::fromKeypair($workerKeypair), 96 | 1 // requires another signer 97 | ); 98 | $addSignerOp = new SetOptionsOp(); 99 | $addSignerOp->updateSigner($workerSigner); 100 | $stellarNetwork->buildTransaction($escrowKeypair) 101 | ->addOperation($addSignerOp) 102 | ->submit($escrowKeypair); 103 | 104 | // Add customer account as second signer of weight 1 105 | $workerSigner = new Signer( 106 | SignerKey::fromKeypair($customerKeypair), 107 | 1 // requires another signer 108 | ); 109 | $addSignerOp = new SetOptionsOp(); 110 | $addSignerOp->updateSigner($workerSigner); 111 | $stellarNetwork->buildTransaction($escrowKeypair) 112 | ->addOperation($addSignerOp) 113 | ->submit($escrowKeypair); 114 | 115 | // Increase thresholds and set master weight to 0 116 | // All operations now require threshold of 2 117 | 118 | $thresholdsOp = new SetOptionsOp(); 119 | $thresholdsOp->setLowThreshold(2); 120 | $thresholdsOp->setMediumThreshold(2); 121 | $thresholdsOp->setHighThreshold(2); 122 | $thresholdsOp->setMasterWeight(0); 123 | $stellarNetwork->buildTransaction($escrowKeypair) 124 | ->addOperation($thresholdsOp) 125 | ->submit($escrowKeypair); 126 | 127 | print PHP_EOL; 128 | print "Finished configuring escrow account" . PHP_EOL; -------------------------------------------------------------------------------- /distributed-worker/composer.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_readme": [ 3 | "This file locks the dependencies of your project to a known state", 4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", 5 | "This file is @generated automatically" 6 | ], 7 | "content-hash": "b54730b239343254eb673961cd29c666", 8 | "packages": [ 9 | { 10 | "name": "christian-riesen/base32", 11 | "version": "1.3.1", 12 | "source": { 13 | "type": "git", 14 | "url": "https://github.com/ChristianRiesen/base32.git", 15 | "reference": "0a31e50c0fa9b1692d077c86ac188eecdcbaf7fa" 16 | }, 17 | "dist": { 18 | "type": "zip", 19 | "url": "https://api.github.com/repos/ChristianRiesen/base32/zipball/0a31e50c0fa9b1692d077c86ac188eecdcbaf7fa", 20 | "reference": "0a31e50c0fa9b1692d077c86ac188eecdcbaf7fa", 21 | "shasum": "" 22 | }, 23 | "require": { 24 | "php": ">=5.3.0" 25 | }, 26 | "require-dev": { 27 | "phpunit/phpunit": "4.*", 28 | "satooshi/php-coveralls": "0.*" 29 | }, 30 | "type": "library", 31 | "extra": { 32 | "branch-alias": { 33 | "dev-master": "1.1.x-dev" 34 | } 35 | }, 36 | "autoload": { 37 | "psr-4": { 38 | "Base32\\": "src/" 39 | } 40 | }, 41 | "notification-url": "https://packagist.org/downloads/", 42 | "license": [ 43 | "MIT" 44 | ], 45 | "authors": [ 46 | { 47 | "name": "Christian Riesen", 48 | "email": "chris.riesen@gmail.com", 49 | "homepage": "http://christianriesen.com", 50 | "role": "Developer" 51 | } 52 | ], 53 | "description": "Base32 encoder/decoder according to RFC 4648", 54 | "homepage": "https://github.com/ChristianRiesen/base32", 55 | "keywords": [ 56 | "base32", 57 | "decode", 58 | "encode", 59 | "rfc4648" 60 | ], 61 | "time": "2016-05-05T11:49:03+00:00" 62 | }, 63 | { 64 | "name": "guzzlehttp/guzzle", 65 | "version": "6.3.0", 66 | "source": { 67 | "type": "git", 68 | "url": "https://github.com/guzzle/guzzle.git", 69 | "reference": "f4db5a78a5ea468d4831de7f0bf9d9415e348699" 70 | }, 71 | "dist": { 72 | "type": "zip", 73 | "url": "https://api.github.com/repos/guzzle/guzzle/zipball/f4db5a78a5ea468d4831de7f0bf9d9415e348699", 74 | "reference": "f4db5a78a5ea468d4831de7f0bf9d9415e348699", 75 | "shasum": "" 76 | }, 77 | "require": { 78 | "guzzlehttp/promises": "^1.0", 79 | "guzzlehttp/psr7": "^1.4", 80 | "php": ">=5.5" 81 | }, 82 | "require-dev": { 83 | "ext-curl": "*", 84 | "phpunit/phpunit": "^4.0 || ^5.0", 85 | "psr/log": "^1.0" 86 | }, 87 | "suggest": { 88 | "psr/log": "Required for using the Log middleware" 89 | }, 90 | "type": "library", 91 | "extra": { 92 | "branch-alias": { 93 | "dev-master": "6.2-dev" 94 | } 95 | }, 96 | "autoload": { 97 | "files": [ 98 | "src/functions_include.php" 99 | ], 100 | "psr-4": { 101 | "GuzzleHttp\\": "src/" 102 | } 103 | }, 104 | "notification-url": "https://packagist.org/downloads/", 105 | "license": [ 106 | "MIT" 107 | ], 108 | "authors": [ 109 | { 110 | "name": "Michael Dowling", 111 | "email": "mtdowling@gmail.com", 112 | "homepage": "https://github.com/mtdowling" 113 | } 114 | ], 115 | "description": "Guzzle is a PHP HTTP client library", 116 | "homepage": "http://guzzlephp.org/", 117 | "keywords": [ 118 | "client", 119 | "curl", 120 | "framework", 121 | "http", 122 | "http client", 123 | "rest", 124 | "web service" 125 | ], 126 | "time": "2017-06-22T18:50:49+00:00" 127 | }, 128 | { 129 | "name": "guzzlehttp/promises", 130 | "version": "v1.3.1", 131 | "source": { 132 | "type": "git", 133 | "url": "https://github.com/guzzle/promises.git", 134 | "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646" 135 | }, 136 | "dist": { 137 | "type": "zip", 138 | "url": "https://api.github.com/repos/guzzle/promises/zipball/a59da6cf61d80060647ff4d3eb2c03a2bc694646", 139 | "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646", 140 | "shasum": "" 141 | }, 142 | "require": { 143 | "php": ">=5.5.0" 144 | }, 145 | "require-dev": { 146 | "phpunit/phpunit": "^4.0" 147 | }, 148 | "type": "library", 149 | "extra": { 150 | "branch-alias": { 151 | "dev-master": "1.4-dev" 152 | } 153 | }, 154 | "autoload": { 155 | "psr-4": { 156 | "GuzzleHttp\\Promise\\": "src/" 157 | }, 158 | "files": [ 159 | "src/functions_include.php" 160 | ] 161 | }, 162 | "notification-url": "https://packagist.org/downloads/", 163 | "license": [ 164 | "MIT" 165 | ], 166 | "authors": [ 167 | { 168 | "name": "Michael Dowling", 169 | "email": "mtdowling@gmail.com", 170 | "homepage": "https://github.com/mtdowling" 171 | } 172 | ], 173 | "description": "Guzzle promises library", 174 | "keywords": [ 175 | "promise" 176 | ], 177 | "time": "2016-12-20T10:07:11+00:00" 178 | }, 179 | { 180 | "name": "guzzlehttp/psr7", 181 | "version": "1.4.2", 182 | "source": { 183 | "type": "git", 184 | "url": "https://github.com/guzzle/psr7.git", 185 | "reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c" 186 | }, 187 | "dist": { 188 | "type": "zip", 189 | "url": "https://api.github.com/repos/guzzle/psr7/zipball/f5b8a8512e2b58b0071a7280e39f14f72e05d87c", 190 | "reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c", 191 | "shasum": "" 192 | }, 193 | "require": { 194 | "php": ">=5.4.0", 195 | "psr/http-message": "~1.0" 196 | }, 197 | "provide": { 198 | "psr/http-message-implementation": "1.0" 199 | }, 200 | "require-dev": { 201 | "phpunit/phpunit": "~4.0" 202 | }, 203 | "type": "library", 204 | "extra": { 205 | "branch-alias": { 206 | "dev-master": "1.4-dev" 207 | } 208 | }, 209 | "autoload": { 210 | "psr-4": { 211 | "GuzzleHttp\\Psr7\\": "src/" 212 | }, 213 | "files": [ 214 | "src/functions_include.php" 215 | ] 216 | }, 217 | "notification-url": "https://packagist.org/downloads/", 218 | "license": [ 219 | "MIT" 220 | ], 221 | "authors": [ 222 | { 223 | "name": "Michael Dowling", 224 | "email": "mtdowling@gmail.com", 225 | "homepage": "https://github.com/mtdowling" 226 | }, 227 | { 228 | "name": "Tobias Schultze", 229 | "homepage": "https://github.com/Tobion" 230 | } 231 | ], 232 | "description": "PSR-7 message implementation that also provides common utility methods", 233 | "keywords": [ 234 | "http", 235 | "message", 236 | "request", 237 | "response", 238 | "stream", 239 | "uri", 240 | "url" 241 | ], 242 | "time": "2017-03-20T17:10:46+00:00" 243 | }, 244 | { 245 | "name": "paragonie/random_compat", 246 | "version": "v2.0.11", 247 | "source": { 248 | "type": "git", 249 | "url": "https://github.com/paragonie/random_compat.git", 250 | "reference": "5da4d3c796c275c55f057af5a643ae297d96b4d8" 251 | }, 252 | "dist": { 253 | "type": "zip", 254 | "url": "https://api.github.com/repos/paragonie/random_compat/zipball/5da4d3c796c275c55f057af5a643ae297d96b4d8", 255 | "reference": "5da4d3c796c275c55f057af5a643ae297d96b4d8", 256 | "shasum": "" 257 | }, 258 | "require": { 259 | "php": ">=5.2.0" 260 | }, 261 | "require-dev": { 262 | "phpunit/phpunit": "4.*|5.*" 263 | }, 264 | "suggest": { 265 | "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." 266 | }, 267 | "type": "library", 268 | "autoload": { 269 | "files": [ 270 | "lib/random.php" 271 | ] 272 | }, 273 | "notification-url": "https://packagist.org/downloads/", 274 | "license": [ 275 | "MIT" 276 | ], 277 | "authors": [ 278 | { 279 | "name": "Paragon Initiative Enterprises", 280 | "email": "security@paragonie.com", 281 | "homepage": "https://paragonie.com" 282 | } 283 | ], 284 | "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", 285 | "keywords": [ 286 | "csprng", 287 | "pseudorandom", 288 | "random" 289 | ], 290 | "time": "2017-09-27T21:40:39+00:00" 291 | }, 292 | { 293 | "name": "paragonie/sodium_compat", 294 | "version": "v1.5.6", 295 | "source": { 296 | "type": "git", 297 | "url": "https://github.com/paragonie/sodium_compat.git", 298 | "reference": "ca9d0656dbd6e6f7b23675ff7abd90d5e9cea054" 299 | }, 300 | "dist": { 301 | "type": "zip", 302 | "url": "https://api.github.com/repos/paragonie/sodium_compat/zipball/ca9d0656dbd6e6f7b23675ff7abd90d5e9cea054", 303 | "reference": "ca9d0656dbd6e6f7b23675ff7abd90d5e9cea054", 304 | "shasum": "" 305 | }, 306 | "require": { 307 | "paragonie/random_compat": "^1|^2", 308 | "php": "^5.2.4|^5.3|^5.4|^5.5|^5.6|^7" 309 | }, 310 | "provide": { 311 | "ext-libsodium": "*", 312 | "ext-sodium": "*" 313 | }, 314 | "require-dev": { 315 | "phpunit/phpunit": "^3|^4|^5" 316 | }, 317 | "suggest": { 318 | "ext-libsodium": "PHP < 7.0: Better performance, password hashing (Argon2i), secure memory management (memzero), and better security.", 319 | "ext-sodium": "PHP >= 7.0: Better performance, password hashing (Argon2i), secure memory management (memzero), and better security." 320 | }, 321 | "type": "library", 322 | "autoload": { 323 | "files": [ 324 | "autoload.php" 325 | ] 326 | }, 327 | "notification-url": "https://packagist.org/downloads/", 328 | "license": [ 329 | "ISC" 330 | ], 331 | "authors": [ 332 | { 333 | "name": "Paragon Initiative Enterprises", 334 | "email": "security@paragonie.com" 335 | }, 336 | { 337 | "name": "Frank Denis", 338 | "email": "jedisct1@pureftpd.org" 339 | } 340 | ], 341 | "description": "Pure PHP implementation of libsodium; uses the PHP extension if it exists", 342 | "keywords": [ 343 | "Authentication", 344 | "BLAKE2b", 345 | "ChaCha20", 346 | "ChaCha20-Poly1305", 347 | "Chapoly", 348 | "Curve25519", 349 | "Ed25519", 350 | "EdDSA", 351 | "Edwards-curve Digital Signature Algorithm", 352 | "Elliptic Curve Diffie-Hellman", 353 | "Poly1305", 354 | "Pure-PHP cryptography", 355 | "RFC 7748", 356 | "RFC 8032", 357 | "Salpoly", 358 | "Salsa20", 359 | "X25519", 360 | "XChaCha20-Poly1305", 361 | "XSalsa20-Poly1305", 362 | "Xchacha20", 363 | "Xsalsa20", 364 | "aead", 365 | "cryptography", 366 | "ecdh", 367 | "elliptic curve", 368 | "elliptic curve cryptography", 369 | "encryption", 370 | "libsodium", 371 | "php", 372 | "public-key cryptography", 373 | "secret-key cryptography", 374 | "side-channel resistant" 375 | ], 376 | "time": "2018-01-30T13:19:20+00:00" 377 | }, 378 | { 379 | "name": "phpseclib/phpseclib", 380 | "version": "2.0.9", 381 | "source": { 382 | "type": "git", 383 | "url": "https://github.com/phpseclib/phpseclib.git", 384 | "reference": "c9a3fe35e20eb6eeaca716d6a23cde03f52d1558" 385 | }, 386 | "dist": { 387 | "type": "zip", 388 | "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/c9a3fe35e20eb6eeaca716d6a23cde03f52d1558", 389 | "reference": "c9a3fe35e20eb6eeaca716d6a23cde03f52d1558", 390 | "shasum": "" 391 | }, 392 | "require": { 393 | "php": ">=5.3.3" 394 | }, 395 | "require-dev": { 396 | "phing/phing": "~2.7", 397 | "phpunit/phpunit": "~4.0", 398 | "sami/sami": "~2.0", 399 | "squizlabs/php_codesniffer": "~2.0" 400 | }, 401 | "suggest": { 402 | "ext-gmp": "Install the GMP (GNU Multiple Precision) extension in order to speed up arbitrary precision integer arithmetic operations.", 403 | "ext-libsodium": "SSH2/SFTP can make use of some algorithms provided by the libsodium-php extension.", 404 | "ext-mcrypt": "Install the Mcrypt extension in order to speed up a few other cryptographic operations.", 405 | "ext-openssl": "Install the OpenSSL extension in order to speed up a wide variety of cryptographic operations." 406 | }, 407 | "type": "library", 408 | "autoload": { 409 | "files": [ 410 | "phpseclib/bootstrap.php" 411 | ], 412 | "psr-4": { 413 | "phpseclib\\": "phpseclib/" 414 | } 415 | }, 416 | "notification-url": "https://packagist.org/downloads/", 417 | "license": [ 418 | "MIT" 419 | ], 420 | "authors": [ 421 | { 422 | "name": "Jim Wigginton", 423 | "email": "terrafrost@php.net", 424 | "role": "Lead Developer" 425 | }, 426 | { 427 | "name": "Patrick Monnerat", 428 | "email": "pm@datasphere.ch", 429 | "role": "Developer" 430 | }, 431 | { 432 | "name": "Andreas Fischer", 433 | "email": "bantu@phpbb.com", 434 | "role": "Developer" 435 | }, 436 | { 437 | "name": "Hans-Jürgen Petrich", 438 | "email": "petrich@tronic-media.com", 439 | "role": "Developer" 440 | }, 441 | { 442 | "name": "Graham Campbell", 443 | "email": "graham@alt-three.com", 444 | "role": "Developer" 445 | } 446 | ], 447 | "description": "PHP Secure Communications Library - Pure-PHP implementations of RSA, AES, SSH2, SFTP, X.509 etc.", 448 | "homepage": "http://phpseclib.sourceforge.net", 449 | "keywords": [ 450 | "BigInteger", 451 | "aes", 452 | "asn.1", 453 | "asn1", 454 | "blowfish", 455 | "crypto", 456 | "cryptography", 457 | "encryption", 458 | "rsa", 459 | "security", 460 | "sftp", 461 | "signature", 462 | "signing", 463 | "ssh", 464 | "twofish", 465 | "x.509", 466 | "x509" 467 | ], 468 | "time": "2017-11-29T06:38:08+00:00" 469 | }, 470 | { 471 | "name": "psr/http-message", 472 | "version": "1.0.1", 473 | "source": { 474 | "type": "git", 475 | "url": "https://github.com/php-fig/http-message.git", 476 | "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" 477 | }, 478 | "dist": { 479 | "type": "zip", 480 | "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", 481 | "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", 482 | "shasum": "" 483 | }, 484 | "require": { 485 | "php": ">=5.3.0" 486 | }, 487 | "type": "library", 488 | "extra": { 489 | "branch-alias": { 490 | "dev-master": "1.0.x-dev" 491 | } 492 | }, 493 | "autoload": { 494 | "psr-4": { 495 | "Psr\\Http\\Message\\": "src/" 496 | } 497 | }, 498 | "notification-url": "https://packagist.org/downloads/", 499 | "license": [ 500 | "MIT" 501 | ], 502 | "authors": [ 503 | { 504 | "name": "PHP-FIG", 505 | "homepage": "http://www.php-fig.org/" 506 | } 507 | ], 508 | "description": "Common interface for HTTP messages", 509 | "homepage": "https://github.com/php-fig/http-message", 510 | "keywords": [ 511 | "http", 512 | "http-message", 513 | "psr", 514 | "psr-7", 515 | "request", 516 | "response" 517 | ], 518 | "time": "2016-08-06T14:39:51+00:00" 519 | }, 520 | { 521 | "name": "symfony/filesystem", 522 | "version": "v3.4.4", 523 | "source": { 524 | "type": "git", 525 | "url": "https://github.com/symfony/filesystem.git", 526 | "reference": "e078773ad6354af38169faf31c21df0f18ace03d" 527 | }, 528 | "dist": { 529 | "type": "zip", 530 | "url": "https://api.github.com/repos/symfony/filesystem/zipball/e078773ad6354af38169faf31c21df0f18ace03d", 531 | "reference": "e078773ad6354af38169faf31c21df0f18ace03d", 532 | "shasum": "" 533 | }, 534 | "require": { 535 | "php": "^5.5.9|>=7.0.8" 536 | }, 537 | "type": "library", 538 | "extra": { 539 | "branch-alias": { 540 | "dev-master": "3.4-dev" 541 | } 542 | }, 543 | "autoload": { 544 | "psr-4": { 545 | "Symfony\\Component\\Filesystem\\": "" 546 | }, 547 | "exclude-from-classmap": [ 548 | "/Tests/" 549 | ] 550 | }, 551 | "notification-url": "https://packagist.org/downloads/", 552 | "license": [ 553 | "MIT" 554 | ], 555 | "authors": [ 556 | { 557 | "name": "Fabien Potencier", 558 | "email": "fabien@symfony.com" 559 | }, 560 | { 561 | "name": "Symfony Community", 562 | "homepage": "https://symfony.com/contributors" 563 | } 564 | ], 565 | "description": "Symfony Filesystem Component", 566 | "homepage": "https://symfony.com", 567 | "time": "2018-01-03T07:37:34+00:00" 568 | }, 569 | { 570 | "name": "zulucrypto/stellar-api", 571 | "version": "v0.3.0", 572 | "source": { 573 | "type": "git", 574 | "url": "https://github.com/zulucrypto/stellar-api.git", 575 | "reference": "b48cc0618e1e9069bff948883fb3708bf120b692" 576 | }, 577 | "dist": { 578 | "type": "zip", 579 | "url": "https://api.github.com/repos/zulucrypto/stellar-api/zipball/b48cc0618e1e9069bff948883fb3708bf120b692", 580 | "reference": "b48cc0618e1e9069bff948883fb3708bf120b692", 581 | "shasum": "" 582 | }, 583 | "require": { 584 | "christian-riesen/base32": "^1.3", 585 | "guzzlehttp/guzzle": "^6.2", 586 | "paragonie/sodium_compat": "^1.0", 587 | "phpseclib/phpseclib": "^2.0.6", 588 | "symfony/filesystem": "^3.3" 589 | }, 590 | "require-dev": { 591 | "phpunit/phpunit": "^6.4" 592 | }, 593 | "type": "library", 594 | "autoload": { 595 | "psr-4": { 596 | "ZuluCrypto\\StellarSdk\\": "src/", 597 | "ZuluCrypto\\StellarSdk\\Test\\": "tests/" 598 | } 599 | }, 600 | "notification-url": "https://packagist.org/downloads/", 601 | "license": [ 602 | "MIT" 603 | ], 604 | "authors": [ 605 | { 606 | "name": "Zulu Crypto", 607 | "email": "zulucrypto@protonmail.com" 608 | } 609 | ], 610 | "description": "API client for the Stellar network", 611 | "time": "2018-02-04T17:49:19+00:00" 612 | } 613 | ], 614 | "packages-dev": [], 615 | "aliases": [], 616 | "minimum-stability": "stable", 617 | "stability-flags": [], 618 | "prefer-stable": false, 619 | "prefer-lowest": false, 620 | "platform": [], 621 | "platform-dev": [] 622 | } 623 | --------------------------------------------------------------------------------