├── LICENSE ├── README.md ├── composer.json └── src └── Minter ├── Contracts └── MinterTxInterface.php ├── Library ├── ECDSA.php ├── Helper.php └── Http.php ├── MinterAPI.php └── SDK ├── MinterCheck.php ├── MinterCoins ├── MinterAddLimitOrderTx.php ├── MinterAddLiquidityTx.php ├── MinterBurnTokenTx.php ├── MinterBuyCoinTx.php ├── MinterBuySwapPoolTx.php ├── MinterCoinTx.php ├── MinterCreateCoinTx.php ├── MinterCreateMultisigTx.php ├── MinterCreateSwapPoolTx.php ├── MinterCreateTokenTx.php ├── MinterDeclareCandidacyTx.php ├── MinterDelegateTx.php ├── MinterEditCandidateCommissionTx.php ├── MinterEditCandidatePublicKeyTx.php ├── MinterEditCandidateTx.php ├── MinterEditCoinOwnerTx.php ├── MinterEditMultisigTx.php ├── MinterLockStakeTx.php ├── MinterLockTx.php ├── MinterMintTokenTx.php ├── MinterMoveStakeTx.php ├── MinterMultiSendTx.php ├── MinterPriceCommissionTx.php ├── MinterRecreateCoinTx.php ├── MinterRecreateTokenTx.php ├── MinterRedeemCheckTx.php ├── MinterRemoveLimitOrderTx.php ├── MinterRemoveLiquidityTx.php ├── MinterSellAllCoinTx.php ├── MinterSellAllSwapPoolTx.php ├── MinterSellCoinTx.php ├── MinterSellSwapPoolTx.php ├── MinterSendCoinTx.php ├── MinterSetCandidateOffTx.php ├── MinterSetCandidateOnTx.php ├── MinterSetHaltBlockTx.php ├── MinterUnbondTx.php └── MinterVoteUpdateTx.php ├── MinterConverter.php ├── MinterDeepLink.php ├── MinterPrefix.php ├── MinterReward.php ├── MinterSignature.php ├── MinterTx.php ├── MinterTxSigner.php └── MinterWallet.php /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018, Respective Authors all rights reserved. 2 | 3 | The MIT License 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. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | ## About 4 | 5 | This is a pure PHP SDK for working with Minter blockchain 6 | 7 | * [Installation](#installing) 8 | * [Minter Api](#using-minterapi) 9 | - Methods: 10 | - [getBalance](#getbalance) 11 | - [getNonce](#getnonce) 12 | - [send](#send) 13 | - [getAddresses](#getaddresses) 14 | - [getStatus](#getstatus) 15 | - [getValidators](#getvalidators) 16 | - [estimateCoinBuy](#estimatecoinbuy) 17 | - [estimateCoinSell](#estimatecoinsell) 18 | - [estimateCoinSellAll](#estimatecoinsellall) 19 | - [getCoinInfo](#getcoininfo) 20 | - [getBlock](#getblock) 21 | - [getEvents](#getevents) 22 | - [getTransaction](#gettransaction) 23 | - [getCandidate](#getcandidate) 24 | - [getCandidates](#getcandidates) 25 | - [estimateTxCommission](#estimatetxcommission) 26 | - [getTransactions](#gettransactions) 27 | - [getUnconfirmedTxs](#getunconfirmedtxs) 28 | - [getMaxGasPrice](#getmaxgasprice) 29 | - [getMinGasPrice](#getmingasprice) 30 | - [getMissedBlocks](#getmissedblocks) 31 | - [getWaitlist](#getwaitlist) 32 | - [getPriceCommissions](#getPriceCommissions) 33 | - [getPriceVotes](#getPriceVotes) 34 | - [getSwapPool](#getSwapPool) 35 | - [getSwapPoolProvider](#getSwapPoolProvider) 36 | - [getLimitOrder](#getLimitOrder) 37 | - [getLimitOrders](#getLimitOrders) 38 | - [getLimitOrdersByCoins](#getLimitOrdersByCoins) 39 | - [Error handling](#error-handling) 40 | 41 | * [Minter SDK](#using-mintersdk) 42 | - [Sign transaction](#sign-transaction) 43 | - [SendCoin](#example-3) 44 | - [SellCoin](#example-4) 45 | - [SellAllCoin](#example-5) 46 | - [BuyCoin](#example-6) 47 | - [CreateCoin](#example-7) 48 | - [DeclareCandidacy](#example-8) 49 | - [Delegate](#example-9) 50 | - [SetCandidateOn](#example-10) 51 | - [SetCandidateOff](#example-11) 52 | - [RedeemCheck](#example-12) 53 | - [Unbond](#example-13) 54 | - [MultiSend](#example-14) 55 | - [EditCandidate](#example-15) 56 | - [CreateMultisig](#example-16) 57 | - [SetHaltBlock](#example-17) 58 | - [RecreateCoin](#example-18) 59 | - [EditCoinOwner](#example-19) 60 | - [EditMultisig](#example-20) 61 | - [EditCandidatePublicKey](#example-21) 62 | - [AddLiquidity](#example-22) 63 | - [RemoveLiquidity](#example-23) 64 | - [SellSwapPool](#example-24) 65 | - [BuySwapPool](#example-25) 66 | - [SellAllSwapPool](#example-26) 67 | - [EditCandidateCommission](#example-27) 68 | - [MintToken](#example-28) 69 | - [BurnToken](#example-29) 70 | - [CreateToken](#example-30) 71 | - [RecreateToken](#example-31) 72 | - [PriceCommission](#example-32) 73 | - [CreateSwapPool](#example-33) 74 | - [AddLimitOrder](#example-34) 75 | - [RemoveLimitOrder](#example-35) 76 | - [Sign transaction with multisignatures](#sign-transaction-with-multisignatures) 77 | - [Get fee of transaction](#get-fee-of-transaction) 78 | - [Decode Transaction](#decode-transaction) 79 | - [Minter Check](#create-minter-check) 80 | - [Minter Wallet](#minter-wallet) 81 | - [Minter Link](#minter-link) 82 | * [Tests](#tests) 83 | 84 | ## Installing 85 | 86 | ```bash 87 | composer require minter/minter-php-sdk 88 | ``` 89 | 90 | ## Using MinterAPI 91 | 92 | You can get all valid responses and full documentation at [Minter Node Api](https://docs.minter.network/) 93 | 94 | Create MinterAPI instance 95 | 96 | ```php 97 | use Minter\MinterAPI; 98 | 99 | $nodeUrl = 'https://minter-node-1.testnet.minter.network:8843/v2/'; // example of a node url 100 | 101 | $api = new MinterAPI($nodeUrl); 102 | ``` 103 | 104 | ### getBalance 105 | 106 | Returns coins list, balance and transaction count (for nonce) of an address. 107 | 108 | `` 109 | getBalance(string $minterAddress, ?int $height = null): \stdClass 110 | `` 111 | 112 | ###### Example 113 | 114 | ```php 115 | $api->getBalance('Mxfe60014a6e9ac91618f5d1cab3fd58cded61ee99') 116 | 117 | // {"jsonrpc": "2.0", "id": "", "result": { "balance": { ... }, "transaction_count": "0"}} 118 | 119 | ``` 120 | 121 | ### getNonce 122 | 123 | Returns next transaction number (nonce) of an address. 124 | 125 | `` 126 | getNonce(string $minterAddress): int 127 | `` 128 | 129 | ###### Example 130 | 131 | ```php 132 | $api->getNonce('Mxfe60014a6e9ac91618f5d1cab3fd58cded61ee99') 133 | ``` 134 | 135 | ### send 136 | 137 | Returns the result of sending signed tx. 138 | 139 | :warning: To ensure that transaction was successfully committed to the blockchain, you need to find the transaction by the hash and ensure that the status code equals to 0. 140 | 141 | `` 142 | send(string $tx): \stdClass 143 | `` 144 | 145 | ###### Example 146 | 147 | ```php 148 | $api->send('f873010101aae98a4d4e540000000000000094fe60014a6e9ac91618f5d1cab3fd58cded61ee99880de0b6b3a764000080801ca0ae0ee912484b9bf3bee785f4cbac118793799450e0de754667e2c18faa510301a04f1e4ed5fad4b489a1065dc1f5255b356ab9a2ce4b24dde35bcb9dc43aba019c') 149 | ``` 150 | 151 | ### getAddresses 152 | 153 | Returns addresses balances. 154 | 155 | `` 156 | getAddresses(array $addresses, ?int $height = null): \stdClass 157 | `` 158 | 159 | ### getStatus 160 | 161 | Returns node status info. 162 | 163 | `` 164 | getStatus(): \stdClass 165 | `` 166 | 167 | ### getValidators 168 | 169 | Returns list of active validators. 170 | 171 | `` 172 | getValidators(?int $height = null, ?int $page = 1, ?int $perPage = null): \stdClass 173 | `` 174 | 175 | ### estimateCoinBuy 176 | 177 | Return estimate of buy coin transaction. 178 | 179 | `` 180 | estimateCoinBuy(string $coinToSell, string $valueToBuy, string $coinToBuy, ?int $height = null, string $swapFrom): \stdClass 181 | `` 182 | 183 | ### estimateCoinSell 184 | 185 | Return estimate of sell coin transaction. 186 | 187 | `` 188 | estimateCoinSell(string $coinToSell, string $valueToSell, string $coinToBuy, ?int $height = null, string $swapFrom): \stdClass 189 | `` 190 | 191 | ### estimateCoinSellAll 192 | 193 | Return estimate of sell coin all transaction. 194 | 195 | `` 196 | estimateCoinSellAll(string $coinToSell, string $valueToSell, string $coinToBuy, ?int $height = null, string $swapFrom): \stdClass 197 | `` 198 | 199 | ### getCoinInfo 200 | 201 | Returns information about coin. 202 | Note: this method does not return information about base coins (MNT and BIP). 203 | 204 | `` 205 | getCoinInfo(string $coin, ?int $height = null): \stdClass 206 | `` 207 | 208 | ### getBlock 209 | 210 | Returns block data at given height. 211 | 212 | `` 213 | getBlock(int $height): \stdClass 214 | `` 215 | 216 | ### getEvents 217 | 218 | Returns events at given height. 219 | 220 | `` 221 | getEvents(int $height): \stdClass 222 | `` 223 | 224 | ### getTransaction 225 | 226 | Returns transaction info. 227 | 228 | `` 229 | getTransaction(string $hash): \stdClass 230 | `` 231 | 232 | ### getCandidate 233 | 234 | Returns candidate’s info by provided public_key. It will respond with 404 code if candidate is not found. 235 | 236 | `` 237 | getCandidate(string $publicKey, ?int $height = null): \stdClass 238 | `` 239 | 240 | ### getCandidates 241 | 242 | Returns list of candidates. 243 | 244 | $height is optional parameter. 245 | 246 | `` 247 | getCandidates(?int $height = null, ?bool $includeStakes = false): \stdClass 248 | `` 249 | 250 | ### estimateTxCommission 251 | 252 | Returns estimate of transaction. 253 | 254 | `` 255 | estimateTxCommission(string $tx, ?int $height = null): \stdClass 256 | `` 257 | 258 | ### getTransactions 259 | 260 | Returns transactions by query. 261 | 262 | `` 263 | getTransactions(string $query, ?int $page = null, ?int $perPage = null): \stdClass 264 | `` 265 | 266 | ### getUnconfirmedTxs 267 | 268 | Returns unconfirmed transactions. 269 | 270 | `` 271 | getUnconfirmedTxs(?int $limit = null): \stdClass 272 | `` 273 | 274 | ### getMaxGasPrice 275 | 276 | Returns current max gas price. 277 | 278 | `` 279 | getMaxGasPrice(?int $height = null): \stdClass 280 | `` 281 | 282 | ### getMinGasPrice 283 | 284 | Returns current min gas price. 285 | 286 | `` 287 | getMinGasPrice(): \stdClass 288 | `` 289 | 290 | ### getMissedBlocks 291 | 292 | Returns missed blocks by validator public key. 293 | 294 | `` 295 | getMissedBlocks(string $pubKey, ?int $height = null): \stdClass 296 | `` 297 | 298 | ### getGenesis 299 | 300 | Returns network genesis. 301 | 302 | `` 303 | getGenesis(): \stdClass 304 | `` 305 | 306 | ### getNetworkInfo 307 | 308 | Returns node network information. 309 | 310 | `` 311 | getNetworkInfo(): \stdClass 312 | `` 313 | 314 | ### getWaitlist 315 | 316 | Returns waitlisted stakes by address 317 | 318 | `` 319 | getWaitlist(string $address, ?string $publicKey = null, ?int $height = null): \stdClass 320 | `` 321 | 322 | ### getWaitlist 323 | 324 | Returns waitlisted stakes by address 325 | 326 | `` 327 | getWaitlist(string $address, ?string $publicKey = null, ?int $height = null): \stdClass 328 | `` 329 | 330 | ### getPriceCommissions 331 | 332 | Returns the list of the commissions that are set up on the Minter Network 333 | 334 | `` 335 | getPriceCommissions(?int $height = null): \stdClass 336 | `` 337 | 338 | ### getPriceVotes 339 | 340 | Returns the list of validators' votes for changing commissions on the network 341 | 342 | `` 343 | getPriceVotes(int $height): \stdClass 344 | `` 345 | 346 | ### getSwapPool 347 | 348 | Returns entire liquidity volume of the swap pool 349 | 350 | `` 351 | getSwapPool(string $coin0, string $coin1, ?int $height = null): \stdClass 352 | `` 353 | 354 | ### getSwapPoolProvider 355 | 356 | Returns liquidity volume of the swap pool provided by specified address 357 | 358 | `` 359 | getSwapPoolProvider(string $coin0, string $coin1, string $provider, ?int $height = null): \stdClass 360 | `` 361 | 362 | ### getLimitOrders 363 | 364 | Returns list of limit orders by ids 365 | 366 | `` 367 | getLimitOrders(array $ids, ?int $height = null): \stdClass 368 | `` 369 | 370 | ### getLimitOrder 371 | 372 | Returns limit order details by id 373 | 374 | `` 375 | getLimitOrder(int $limitOrderId, ?int $height = null): \stdClass 376 | `` 377 | 378 | ### getLimitOrdersByCoins 379 | 380 | Returns limit orders related to sell and buy coins 381 | 382 | `` 383 | getLimitOrdersByCoins(string $sellCoin, string $buyCoin, int $limit = null, ?int $height = null): \stdClass 384 | `` 385 | 386 | 387 | 388 | ### Error handling 389 | 390 | Example of how you can handle errors and get the response body. 391 | 392 | ```php 393 | use Minter\MinterAPI; 394 | use GuzzleHttp\Exception\RequestException; 395 | 396 | // create instance 397 | $api = new MinterAPI('node url here'); 398 | 399 | try { 400 | // success response 401 | $response = $api->send('signed tx here'); 402 | } catch(RequestException $exception) { 403 | // short exception message 404 | $message = $exception->getMessage(); 405 | 406 | // error response in json 407 | $content = $exception->getResponse() 408 | ->getBody() 409 | ->getContents(); 410 | 411 | // error response as array 412 | $error = json_decode($content, true); 413 | } 414 | ``` 415 | 416 | 417 | ## Using MinterSDK 418 | 419 | ### Sign transaction 420 | 421 | Returns a signed tx. 422 | 423 | ###### Example 424 | 425 | * Sign the SendCoin transaction 426 | * Constructor: ```MinterSendCoinTx($coin, $to, $value)``` 427 | 428 | ```php 429 | use Minter\SDK\MinterTx; 430 | use Minter\SDK\MinterCoins\MinterSendCoinTx; 431 | 432 | $data = new MinterSendCoinTx($coinID, 'Mxfe60014a6e9ac91618f5d1cab3fd58cded61ee99', '10'); 433 | $tx = new MinterTx($nonce, $data); 434 | 435 | $tx->sign('your private key'); 436 | ``` 437 | 438 | At all type of transactions you can also set optional fields: 439 | gas price, gas coin, payload, serviceData, chain id 440 | 441 | ```php 442 | use Minter\SDK\MinterTx; 443 | use Minter\SDK\MinterCoins\MinterSendCoinTx; 444 | 445 | $data = new MinterSendCoinTx($coinID, 'Mxfe60014a6e9ac91618f5d1cab3fd58cded61ee99', '10'); 446 | $tx = (new MinterTx($nonce, $data)) 447 | ->setChainID(MinterTx::TESTNET_CHAIN_ID) 448 | ->setGasPrice(1) 449 | ->setGasCoin(MinterTx::BASE_COIN_ID) 450 | ->setPayload('some payload') 451 | ->setServiceData('some data'); 452 | 453 | $tx->sign('your private key'); 454 | ``` 455 | 456 | ###### Example 457 | * Sign the SellCoin transaction 458 | * Constructor: ```MinterSellCoinTx($coinToSell, $valueToSell, $coinToBuy, $minimumValueToBuy)``` 459 | 460 | ```php 461 | use Minter\SDK\MinterTx; 462 | use Minter\SDK\MinterCoins\MinterSellCoinTx; 463 | 464 | $data = new MinterSellCoinTx(123, '1', 321, '1'); 465 | $tx = new MinterTx($nonce, $data); 466 | 467 | $tx->sign('your private key'); 468 | ``` 469 | 470 | ###### Example 471 | * Sign the SellAllCoin transaction 472 | * Constructor: ```MinterSellAllCoinTx($coinToSell, $coinToBuy, $minimumValueToBuy)``` 473 | 474 | ```php 475 | use Minter\SDK\MinterTx; 476 | use Minter\SDK\MinterCoins\MinterSellAllCoinTx; 477 | 478 | $data = new MinterSellAllCoinTx(123, 321, '1'); 479 | $tx = new MinterTx($nonce, $data); 480 | 481 | $tx->sign('your private key'); 482 | ``` 483 | 484 | ###### Example 485 | * Sign the BuyCoin transaction 486 | * Constructor: ```MinterBuyCoinTx($coinToBuy, $valueToBuy, $coinToSell, $maximumValueToSell)``` 487 | 488 | ```php 489 | use Minter\SDK\MinterTx; 490 | use Minter\SDK\MinterCoins\MinterBuyCoinTx; 491 | 492 | $data = new MinterBuyCoinTx(123, '1', 321, '1'); 493 | $tx = new MinterTx($nonce, $data); 494 | 495 | $tx->sign('your private key'); 496 | ``` 497 | 498 | ###### Example 499 | * Sign the CreateCoin transaction 500 | * Constructor: ```MinterCreateCoinTx($name, $symbol, $amount, $reserve, $crr, $maxSupply)``` 501 | 502 | ```php 503 | use Minter\SDK\MinterTx; 504 | use Minter\SDK\MinterCoins\MinterCreateCoinTx; 505 | 506 | $data = new MinterCreateCoinTx('TEST COIN', 'TEST', '10000', '10', 10, '10000'); 507 | $tx = new MinterTx($nonce, $data); 508 | 509 | $tx->sign('your private key'); 510 | ``` 511 | 512 | ###### Example 513 | * Sign the DeclareCandidacy transaction 514 | * Constructor: ```MinterDeclareCandidacyTx($address, $publicKey, $commission, $coin, $stake)``` 515 | 516 | ```php 517 | use Minter\SDK\MinterTx; 518 | use Minter\SDK\MinterCoins\MinterDeclareCandidacyTx; 519 | 520 | $data = new MinterDeclareCandidacyTx( 521 | 'Mxa7bc33954f1ce855ed1a8c768fdd32ed927def47', 522 | 'Mp023853f15fc1b1073ad7a1a0d4490a3b1fadfac00f36039b6651bc4c7f52ba9c02', 523 | 10, 0, '10000' 524 | ); 525 | 526 | $tx = new MinterTx($nonce, $data); 527 | $tx->sign('your private key'); 528 | ``` 529 | 530 | ###### Example 531 | * Sign the Delegate transaction 532 | * Constructor: ```MinterDelegateTx($publicKey, $coin, $stake)``` 533 | 534 | ```php 535 | use Minter\SDK\MinterTx; 536 | use Minter\SDK\MinterCoins\MinterDelegateTx; 537 | 538 | $data = new MinterDelegateTx('Mp0eb98ea04ae466d8d38f490db3c99b3996a90e24243952ce9822c6dc1e2c1a43', 123, '10000'); 539 | $tx = new MinterTx($nonce, $data); 540 | 541 | $tx->sign('your private key'); 542 | ``` 543 | 544 | ###### Example 545 | * Sign the SetCandidateOn transaction 546 | * Constructor: ```MinterSetCandidateOnTx($publicKey)``` 547 | 548 | ```php 549 | use Minter\SDK\MinterTx; 550 | use Minter\SDK\MinterCoins\MinterSetCandidateOnTx; 551 | 552 | $data = new MinterSetCandidateOnTx('Mp0eb98ea04ae466d8d38f490db3c99b3996a90e24243952ce9822c6dc1e2c1a43'); 553 | $tx = new MinterTx($nonce, $data); 554 | 555 | $tx->sign('your private key'); 556 | ``` 557 | 558 | ###### Example 559 | * Sign the SetCandidateOff transaction 560 | * Constructor: ```MinterSetCandidateOffTx($publicKey)``` 561 | 562 | ```php 563 | use Minter\SDK\MinterTx; 564 | use Minter\SDK\MinterCoins\MinterSetCandidateOffTx; 565 | 566 | $data = new MinterSetCandidateOffTx('Mp0eb98ea04ae466d8d38f490db3c99b3996a90e24243952ce9822c6dc1e2c1a43'); 567 | $tx = new MinterTx($nonce, $data); 568 | 569 | $tx->sign('your private key'); 570 | ``` 571 | 572 | ###### Example 573 | * Sign the RedeemCheck transaction 574 | * Constructor: ```MinterRedeemCheckTx($check, $proof)``` 575 | 576 | ```php 577 | use Minter\SDK\MinterTx; 578 | use Minter\SDK\MinterCoins\MinterRedeemCheckTx; 579 | 580 | $data = new MinterRedeemCheckTx('your check', 'created by MinterCheck proof'); 581 | $tx = new MinterTx($nonce, $data); 582 | 583 | $tx->sign('your private key'); 584 | ``` 585 | 586 | ###### Example 587 | * Sign the Unbond transaction 588 | * Constructor: ```MinterUnbondTx($publicKey, $coin, $value)``` 589 | 590 | ```php 591 | use Minter\SDK\MinterTx; 592 | use Minter\SDK\MinterCoins\MinterUnbondTx; 593 | 594 | $data = new MinterUnbondTx('Mp....', 123, '10000'); 595 | $tx = new MinterTx($nonce, $data); 596 | 597 | $tx->sign('your private key'); 598 | ``` 599 | 600 | ###### Example 601 | * Sign the MultiSend transaction 602 | * Constructor: ```MinterMultiSendTx($list)``` 603 | 604 | ```php 605 | use Minter\SDK\MinterTx; 606 | use Minter\SDK\MinterCoins\MinterSendCoinTx; 607 | use Minter\SDK\MinterCoins\MinterMultiSendTx; 608 | 609 | $data = new MinterMultiSendTx([ 610 | new MinterSendCoinTx(0, 'Mxfe60014a6e9ac91618f5d1cab3fd58cded61ee99', '15'), 611 | new MinterSendCoinTx(123, 'Mxfe60014a6e9ac91618f5d1cab3fd58cded61ee92', '10') 612 | ]); 613 | 614 | $tx = new MinterTx($nonce, $data); 615 | $tx->sign('your private key'); 616 | ``` 617 | 618 | ###### Example 619 | * Sign the EditCandidate transaction 620 | * Constructor: ```MinterEditCandidateTx($publicKey, $rewardAddress, $ownerAddress, $controlAddress)``` 621 | 622 | ```php 623 | use Minter\SDK\MinterTx; 624 | use Minter\SDK\MinterCoins\MinterEditCandidateTx; 625 | 626 | $data = new MinterEditCandidateTx('candidate public key', 'Minter address for rewards', 'Minter address of owner', 'Minter address for control'); 627 | $tx = new MinterTx($nonce, $data); 628 | 629 | $tx->sign('your private key'); 630 | ``` 631 | 632 | ###### Example 633 | * Sign the CreateMultisig transaction 634 | * Constructor: ```MinterCreateMultisigTx($threshold, $weights, $addresses)``` 635 | 636 | ```php 637 | use Minter\SDK\MinterTx; 638 | use Minter\SDK\MinterCoins\MinterCreateMultisigTx; 639 | 640 | $data = new MinterCreateMultisigTx(7, [1, 3, 5], [ 641 | 'Mxee81347211c72524338f9680072af90744333143', 642 | 'Mxee81347211c72524338f9680072af90744333145', 643 | 'Mxee81347211c72524338f9680072af90744333144' 644 | ]); 645 | 646 | $tx = new MinterTx($nonce, $data); 647 | $tx->sign('your private key'); 648 | ``` 649 | 650 | ###### Example 651 | * Sign the SetHaltBlock transaction 652 | * Constructor: ```MinterSetHaltBlockTx($publicKey, $height)``` 653 | 654 | ```php 655 | use Minter\SDK\MinterTx; 656 | use Minter\SDK\MinterCoins\MinterSetHaltBlockTx; 657 | 658 | $data = new MinterSetHaltBlockTx('your public key', 236503); 659 | $tx = new MinterTx($nonce, $data); 660 | $tx->sign('your private key'); 661 | ``` 662 | 663 | ###### Example 664 | * Sign the RecreateCoin transaction 665 | * Constructor: ```MinterRecreateCoinTx($name, $symbol, $amount, $reserve, $crr, $maxSupply)``` 666 | 667 | ```php 668 | use Minter\SDK\MinterTx; 669 | use Minter\SDK\MinterCoins\MinterRecreateCoinTx; 670 | 671 | $data = new MinterRecreateCoinTx('TEST', '10000', '10', 10000, 10, '10000'); 672 | $tx = new MinterTx($nonce, $data); 673 | $tx->sign('your private key'); 674 | ``` 675 | 676 | ###### Example 677 | * Sign the EditCoinOwner transaction 678 | * Constructor: ```MinterEditCoinOwnerTx($symbol, $newOwner)``` 679 | 680 | ```php 681 | use Minter\SDK\MinterTx; 682 | use Minter\SDK\MinterCoins\MinterEditCoinOwnerTx; 683 | 684 | $data = new MinterEditCoinOwnerTx('COINSYMBOL', 'Mxee81347211c72524338f9680072af90744333145'); 685 | $tx = new MinterTx($nonce, $data); 686 | $tx->sign('your private key'); 687 | ``` 688 | 689 | ###### Example 690 | * Sign the EditMultisig transaction 691 | * Constructor: ```MinterEditMultisigTx($threshold, $weights, $addresses)``` 692 | 693 | ```php 694 | use Minter\SDK\MinterTx; 695 | use Minter\SDK\MinterCoins\MinterEditMultisigTx; 696 | 697 | $data = new MinterEditMultisigTx(1, [1, 2], ['Mxee81347211c72524338f9680072af90744333145', 'Mxee81347211c72524338f9680072af90744333146']); 698 | $tx = new MinterTx($nonce, $data); 699 | $tx->sign('your private key'); 700 | ``` 701 | 702 | ###### Example 703 | * Sign the EditCandidatePublicKey transaction 704 | * Constructor: ```MinterEditCandidatePublicKeyTx($publicKey, $newPublicKey)``` 705 | 706 | ```php 707 | use Minter\SDK\MinterTx; 708 | use Minter\SDK\MinterCoins\MinterEditCandidatePublicKeyTx; 709 | 710 | $data = new MinterEditCandidatePublicKeyTx('public key', 'new public key....'); 711 | $tx = new MinterTx($nonce, $data); 712 | $tx->sign('your private key'); 713 | ``` 714 | 715 | ###### Example 716 | * Sign the AddLiquidity transaction 717 | * Constructor: ```MinterAddLiquidityTx($coin0, $coin1, $volume0, $maximumVolume1)``` 718 | 719 | ```php 720 | use Minter\SDK\MinterTx; 721 | use Minter\SDK\MinterCoins\MinterAddLiquidityTx; 722 | 723 | $data = new MinterAddLiquidityTx(0, 1, '1000', '2000'); 724 | $tx = new MinterTx($nonce, $data); 725 | $tx->sign('your private key'); 726 | ``` 727 | 728 | ###### Example 729 | * Sign the RemoveLiquidity transaction 730 | * Constructor: ```MinterRemoveLiquidityTx($coin0, $coin1, $liquidity, $minimumVolume0, $minimumVolume1)``` 731 | 732 | ```php 733 | use Minter\SDK\MinterTx; 734 | use Minter\SDK\MinterCoins\MinterRemoveLiquidityTx; 735 | 736 | $data = new MinterRemoveLiquidityTx(0, 1, '2000', '500', '1000'); 737 | $tx = new MinterTx($nonce, $data); 738 | $tx->sign('your private key'); 739 | ``` 740 | 741 | ###### Example 742 | * Sign the SellSwapPool transaction 743 | * Constructor: ```MinterSellSwapPoolTx(array $coins, $valueToSell, $minimumValueToBuy)``` 744 | 745 | ```php 746 | use Minter\SDK\MinterTx; 747 | use Minter\SDK\MinterCoins\MinterSellSwapPoolTx; 748 | 749 | $data = new MinterSellSwapPoolTx([1, 2], '20', '2'); 750 | $tx = new MinterTx($nonce, $data); 751 | $tx->sign('your private key'); 752 | ``` 753 | 754 | ###### Example 755 | * Sign the BuySwapPool transaction 756 | * Constructor: ```MinterBuySwapPoolTx($coins, $valueToBuy, $maximumValueToSell)``` 757 | 758 | ```php 759 | use Minter\SDK\MinterTx; 760 | use Minter\SDK\MinterCoins\MinterBuySwapPoolTx; 761 | 762 | $data = new MinterBuySwapPoolTx([2, 3], '3', '5000'); 763 | $tx = new MinterTx($nonce, $data); 764 | $tx->sign('your private key'); 765 | ``` 766 | 767 | ###### Example 768 | * Sign the SellAllSwapPool transaction 769 | * Constructor: ```MinterSellAllSwapPoolTx(array $coins, $minimumValueToBuy)``` 770 | 771 | ```php 772 | use Minter\SDK\MinterTx; 773 | use Minter\SDK\MinterCoins\MinterSellAllSwapPoolTx; 774 | 775 | $data = new MinterSellAllSwapPoolTx([1, 4, 5], '100'); 776 | $tx = new MinterTx($nonce, $data); 777 | $tx->sign('your private key'); 778 | ``` 779 | 780 | ###### Example 781 | * Sign the EditCandidateCommission transaction 782 | * Constructor: ```MinterEditCandidateCommissionTx($publicKey, $commission)``` 783 | 784 | ```php 785 | use Minter\SDK\MinterTx; 786 | use Minter\SDK\MinterCoins\MinterEditCandidateCommissionTx; 787 | 788 | $data = new MinterEditCandidateCommissionTx('public key', 77); 789 | $tx = new MinterTx($nonce, $data); 790 | $tx->sign('your private key'); 791 | ``` 792 | 793 | ###### Example 794 | * Sign the MintToken transaction 795 | * Constructor: ```MinterMintTokenTx($coin, $value)``` 796 | 797 | ```php 798 | use Minter\SDK\MinterTx; 799 | use Minter\SDK\MinterCoins\MinterMintTokenTx; 800 | 801 | $data = new MinterMintTokenTx(2, '3000'); 802 | $tx = new MinterTx($nonce, $data); 803 | $tx->sign('your private key') 804 | ``` 805 | 806 | ###### Example 807 | * Sign the BurnToken transaction 808 | * Constructor: ```MinterBurnTokenTx($coin, $value)``` 809 | 810 | ```php 811 | use Minter\SDK\MinterTx; 812 | use Minter\SDK\MinterCoins\MinterBurnTokenTx; 813 | 814 | $data = new MinterBurnTokenTx(3, '100000'); 815 | $tx = new MinterTx($nonce, $data); 816 | $tx->sign('your private key') 817 | ``` 818 | 819 | ###### Example 820 | * Sign the CreateToken transaction 821 | * Constructor: ```MinterCreateTokenTx($name, $symbol, $initialAmount, $maxSupply, $mintable, $burnable)``` 822 | 823 | ```php 824 | use Minter\SDK\MinterTx; 825 | use Minter\SDK\MinterCoins\MinterCreateTokenTx; 826 | 827 | $data = new MinterCreateTokenTx('TEST COIN IS MINTABLE ONLY', 'TEST', '10000', '50000', true, false); 828 | $tx = new MinterTx($nonce, $data); 829 | $tx->sign('your private key') 830 | ``` 831 | 832 | ###### Example 833 | * Sign the RecreateToken transaction 834 | * Constructor: ```MinterRecreateTokenTx($name, $symbol, $initialAmount, $maxSupply, $mintable, $burnable)``` 835 | 836 | ```php 837 | use Minter\SDK\MinterTx; 838 | use Minter\SDK\MinterCoins\MinterRecreateTokenTx; 839 | 840 | $data = new MinterRecreateTokenTx('TEST COIN IS TURNED TO BE BURNABLE ONLY', 'TEST', '50000', '50000', false, true); 841 | $tx = new MinterTx($nonce, $data); 842 | $tx->sign('your private key') 843 | ``` 844 | 845 | ###### Example 846 | * Sign the PriceCommission transaction 847 | * Constructor: ```MinterPriceCommissionTx( 848 | $pubKey, 849 | $height, 850 | $coin, 851 | $payloadByte, 852 | $send, 853 | $buyBancor, 854 | $sellBancor, 855 | $sellAllBancor, 856 | $buyPoolBase, 857 | $buyPoolDelta, 858 | $sellPoolBase, 859 | $sellPoolDelta, 860 | $sellAllPoolBase, 861 | $sellAllPoolDelta, 862 | $createTicker3, 863 | $createTicker4, 864 | $createTicker5, 865 | $createTicker6, 866 | $createTicker7to10, 867 | $createCoin, 868 | $createToken, 869 | $recreateCoin, 870 | $recreateToken, 871 | $declareCandidacy, 872 | $delegate, 873 | $unbond, 874 | $redeemCheck, 875 | $setCandidateOn, 876 | $setCandidateOff, 877 | $createMultisig, 878 | $multisendBase, 879 | $multisendDelta, 880 | $editCandidate, 881 | $setHaltBlock, 882 | $editTickerOwner, 883 | $editMultisig, 884 | $editCandidatePublicKey, 885 | $createSwapPool, 886 | $addLiquidity, 887 | $removeLiquidity, 888 | $editCandidateCommission, 889 | $burnToken, 890 | $mintToken, 891 | $voteCommission, 892 | $voteUpdate 893 | )``` 894 | 895 | ```php 896 | use Minter\SDK\MinterTx; 897 | use Minter\SDK\MinterCoins\MinterPriceCommissionTx; 898 | 899 | $data = new MinterPriceCommissionTx('public key', 100000,0,'1','2','3','4','5','6','7','8','9','10','11','12','13','14','15','16','17','18','19','20','21','22','23','24','25','26','27','28','29','30','31','32','33','34','35','36','37','38','39','40','41', '42'); 900 | $tx = new MinterTx($nonce, $data); 901 | $tx->sign('your private key'); 902 | ``` 903 | 904 | ###### Example 905 | * Sign the CreateSwapPoll transaction 906 | * Constructor: ```MinterCreateSwapPoolTx($coin0, $coin1, $volume0, $volume1)``` 907 | 908 | ```php 909 | use Minter\SDK\MinterTx; 910 | use Minter\SDK\MinterCoins\MinterCreateSwapPoolTx; 911 | 912 | $data = new MinterCreateSwapPoolTx(1, 2, '11000', '22000'); 913 | $tx = new MinterTx($nonce, $data); 914 | $tx->sign('your private key') 915 | ``` 916 | 917 | ###### Example 918 | * Sign the AddLimitOrder transaction 919 | * Constructor: ```MinterAddLimitOrderTx($coinToSell, $valueToSell, $coinToBuy, $valueToBuy)``` 920 | 921 | ```php 922 | use Minter\SDK\MinterTx; 923 | use Minter\SDK\MinterCoins\MinterAddLimitOrderTx; 924 | 925 | $data = new MinterAddLimitOrderTx(0, '10', 1841, '7'); 926 | $tx = new MinterTx($nonce, $data); 927 | $tx->sign('your private key') 928 | ``` 929 | 930 | ###### Example 931 | * Sign the RemoveLimitOrder transaction 932 | * Constructor: ```MinterRemoveLimitOrderTx($id)``` 933 | 934 | ```php 935 | use Minter\SDK\MinterTx; 936 | use Minter\SDK\MinterCoins\MinterRemoveLimitOrderTx; 937 | 938 | $data = new MinterRemoveLimitOrderTx($limitOrderId); 939 | $tx = new MinterTx($nonce, $data); 940 | $tx->sign('your private key') 941 | ``` 942 | 943 | ### Sign transaction with multisignatures 944 | 945 | Returns a signed tx. 946 | 947 | ###### Example 948 | 949 | * To sign transaction with multisignatures, you need to call signMultisig method 950 | and pass multisig Minter address and his private keys (in any order). 951 | 952 | ```php 953 | use Minter\SDK\MinterTx; 954 | use Minter\SDK\MinterCoins\MinterSendCoinTx; 955 | 956 | $data = new MinterSendCoinTx(123, 'Mxfe60014a6e9ac91618f5d1cab3fd58cded61ee99', '10'); 957 | $tx = new MinterTx($nonce, $data); 958 | 959 | $signedTx = $tx->signMultisig('Mxdb4f4b6942cb927e8d7e3a1f602d0f1fb43b5bd2', [ 960 | 'b354c3d1d456d5a1ddd65ca05fd710117701ec69d82dac1858986049a0385af9', 961 | '38b7dfb77426247aed6081f769ed8f62aaec2ee2b38336110ac4f7484478dccb', 962 | '94c0915734f92dd66acfdc48f82b1d0b208efd544fe763386160ec30c968b4af' 963 | ]) 964 | ``` 965 | 966 | ###### Example 967 | 968 | * To get the signature of transaction (not signed transaction) 969 | you need to call createSignature 970 | 971 | ```php 972 | use Minter\SDK\MinterTx; 973 | use Minter\SDK\MinterCoins\MinterSendCoinTx; 974 | 975 | $data = new MinterSendCoinTx(123, 'Mxfe60014a6e9ac91618f5d1cab3fd58cded61ee99', '10'); 976 | $tx = new MinterTx($nonce, $data); 977 | 978 | $txSignature = $tx->createSignature($privateKey); 979 | ``` 980 | 981 | ###### Example 982 | 983 | * To sign transaction with ready signatures, you need to call signMultisigBySigns method 984 | and pass multisig Minter address and your signatures (in any order). 985 | 986 | ```php 987 | use Minter\SDK\MinterTx; 988 | use Minter\SDK\MinterCoins\MinterSendCoinTx; 989 | 990 | $data = new MinterSendCoinTx(123, 'Mxfe60014a6e9ac91618f5d1cab3fd58cded61ee99', '10'); 991 | $tx = new MinterTx($nonce, $data); 992 | 993 | $signature1 = $tx->createSignature($privateKey1); 994 | $signature2 = $tx->createSignature($privateKey2); 995 | $signature3 = $tx->createSignature($privateKey3); 996 | 997 | $signedTx = $tx->signMultisigBySigns('Mxdb4f4b6942cb927e8d7e3a1f602d0f1fb43b5bd2', [ 998 | $signature1, $signature2, $signature3 999 | ]) 1000 | ``` 1001 | 1002 | ### Get fee of transaction 1003 | 1004 | * Calculate fee of transaction. You can get fee AFTER signing or decoding transaction. 1005 | ```php 1006 | use Minter\SDK\MinterTx; 1007 | 1008 | $tx = new MinterTx(...); 1009 | $tx->getFee(); 1010 | ``` 1011 | 1012 | ### Decode transaction 1013 | 1014 | Returns an array with transaction data. 1015 | 1016 | ###### Example 1017 | 1018 | * Decode transaction 1019 | 1020 | ```php 1021 | use Minter\SDK\MinterTx; 1022 | 1023 | $tx = MinterTx::decode('transaction raw starting from 0x...'); 1024 | 1025 | // $tx->getSenderAddress() 1026 | // $tx->getData() 1027 | // $tx->getNonce() 1028 | // $tx->getChainID() 1029 | // $tx->getGasPrice() 1030 | // $tx->getPayload() 1031 | // $tx->getSignatureData() 1032 | 1033 | ``` 1034 | 1035 | ### Create Minter Check 1036 | 1037 | ###### Example 1038 | 1039 | * Create check 1040 | 1041 | ```php 1042 | use Minter\SDK\MinterCheck; 1043 | 1044 | $check = new MinterCheck([ 1045 | 'nonce' => $nonce, 1046 | 'chainId' => MinterTx::MAINNET_CHAIN_ID, // or MinterTx::TESTNET_CHAIN_ID 1047 | 'dueBlock' => 999999, 1048 | 'coin' => 'MNT', 1049 | 'value' => '10', 1050 | 'gasCoin' => 'MNT' 1051 | ], 'your pass phrase'); 1052 | 1053 | echo $check->sign('your private key here'); 1054 | 1055 | // Mc....... 1056 | 1057 | ``` 1058 | 1059 | * Create proof 1060 | 1061 | ```php 1062 | use Minter\SDK\MinterCheck; 1063 | 1064 | $check = new MinterCheck('your Minter address here', 'your pass phrase'); 1065 | 1066 | echo $check->createProof(); 1067 | ``` 1068 | 1069 | * Decode check 1070 | 1071 | ```php 1072 | use Minter\SDK\MinterCheck; 1073 | 1074 | $check = new MinterCheck('your Minter check here'); 1075 | 1076 | $check->getBody(); // check body 1077 | 1078 | $check->getOwnerAddress(); // check owner address 1079 | ``` 1080 | 1081 | ### Minter Wallet 1082 | 1083 | ###### Example 1084 | 1085 | * Create wallet. 1086 | 1087 | ```php 1088 | use Minter\SDK\MinterWallet; 1089 | 1090 | $wallet = new MinterWallet(); 1091 | 1092 | // $wallet->getPublicKey(); 1093 | // $wallet->getPrivateKey(); 1094 | // $wallet->getMnemonic(); 1095 | // $wallet->getAddress(); 1096 | ``` 1097 | 1098 | * Create wallet from mnemonic 1099 | 1100 | ```php 1101 | use Minter\SDK\MinterWallet; 1102 | 1103 | $wallet = MinterWallet::createFromMnemonic($mnemonic); 1104 | ``` 1105 | 1106 | * Create wallet from private key 1107 | 1108 | ```php 1109 | use Minter\SDK\MinterWallet; 1110 | 1111 | $wallet = MinterWallet::createFromPrivate($privateKey); 1112 | ``` 1113 | 1114 | ### Minter Link 1115 | 1116 | ###### Example 1117 | 1118 | * Create Minter deep link. 1119 | * You can pass data of any Minter transaction to the constructor. 1120 | 1121 | ```php 1122 | use Minter\SDK\MinterDeepLink; 1123 | use Minter\SDK\MinterCoins\MinterSendCoinTx; 1124 | 1125 | $txData = new MinterSendCoinTx(123, 'Mx18467bbb64a8edf890201d526c35957d82be3d95', '1.23456789'); 1126 | $link = new MinterDeepLink($txData); 1127 | $link->encode(); // returns encoded link as string 1128 | ``` 1129 | 1130 | * You can define optional fields such as host, payload, nonce, gas price, gas coin, check password. 1131 | 1132 | ```php 1133 | use Minter\SDK\MinterDeepLink; 1134 | use Minter\SDK\MinterCoins\MinterSendCoinTx; 1135 | 1136 | $txData = new MinterSendCoinTx(123, 'Mx18467bbb64a8edf890201d526c35957d82be3d95', '1.23456789'); 1137 | $link = new MinterDeepLink($txData); 1138 | 1139 | $link->setPayload('Hello World') 1140 | ->setNonce($nonce) 1141 | ->setGasPrice($gasPrice) 1142 | ->setGasCoin($gasCoin) 1143 | ->setHost('https://testnet.bip.to/tx') 1144 | ->setPassword('some check password'); 1145 | 1146 | $link->encode(); // returns encoded link as string 1147 | ``` 1148 | 1149 | 1150 | ## Tests 1151 | 1152 | To run unit tests: 1153 | 1154 | ```bash 1155 | vendor/bin/phpunit tests 1156 | ``` 1157 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "minter/minter-php-sdk", 3 | "autoload": { 4 | "psr-0" : { 5 | "Minter\\" : "src" 6 | } 7 | }, 8 | "require": { 9 | "php": "^7.1.3|^8.0", 10 | "ext-bcmath": "*", 11 | "ext-json": "*", 12 | "ext-gmp": "*", 13 | "kornrunner/keccak": "^1.0", 14 | "guzzlehttp/guzzle": "^6.3|^7.3", 15 | "minter/minter-php-bip-44": "^1.2", 16 | "bitwasp/bitcoin-lib": "^1.0", 17 | "simplito/elliptic-php": "^1.0", 18 | "minter/php-rlp": "^1.0.0" 19 | }, 20 | "require-dev": { 21 | "phpunit/phpunit": "^7|^9.5" 22 | }, 23 | "minimum-stability": "dev", 24 | "prefer-stable": true 25 | } 26 | -------------------------------------------------------------------------------- /src/Minter/Contracts/MinterTxInterface.php: -------------------------------------------------------------------------------- 1 | $privateKey, 31 | 'privEnc' => 'hex' 32 | ]); 33 | 34 | $publicKey = $keyPair->getPublic('hex'); 35 | 36 | return substr($publicKey, 2, 130); 37 | } 38 | 39 | /** 40 | * Sign using pure PHP library 41 | * 42 | * @param string $message 43 | * @param string $privateKey 44 | * @return array 45 | */ 46 | public static function sign(string $message, string $privateKey): array 47 | { 48 | // create elliptic curve and sign 49 | $ellipticCurve = new EC('secp256k1'); 50 | $signature = $ellipticCurve->sign($message, $privateKey, 'hex', ['canonical' => true]); 51 | 52 | // convert to hex 53 | $r = $signature->r->toString('hex'); 54 | $s = $signature->s->toString('hex'); 55 | $recovery = $signature->recoveryParam; 56 | 57 | return self::encodeSign($r, $s, $recovery); 58 | } 59 | 60 | 61 | /** 62 | * Recover public key using pure PHP library 63 | * 64 | * @param string $msg 65 | * @param EC\Signature $signature 66 | * @return string 67 | * @throws \Exception 68 | */ 69 | public static function recover(string $msg, EC\Signature $signature): string 70 | { 71 | // define the recovery param 72 | $recovery = $signature->recoveryParam === self::V_BITS ? 0 : 1; 73 | 74 | // define the signature 75 | $signature = [ 76 | 'r' => $signature->r->toString('hex'), 77 | 's' => $signature->s->toString('hex'), 78 | 'recoveryParam' => $recovery 79 | ]; 80 | 81 | // create elliptic curve 82 | $ellipticCurve = new EC('secp256k1'); 83 | $point = $ellipticCurve->recoverPubKey($msg, $signature, $recovery, 'hex'); 84 | 85 | // create key pair from point 86 | $key = new KeyPair($ellipticCurve, [ 87 | 'pub' => $point, 88 | 'pubEnc' => 'hex' 89 | ]); 90 | 91 | return substr($key->getPublic('hex'), 2, 130); 92 | } 93 | 94 | /** 95 | * Encore result params (V, R , S) 96 | * 97 | * @param string $r 98 | * @param string $s 99 | * @param int $recovery 100 | * @return array 101 | */ 102 | protected static function encodeSign(string $r, string $s, int $recovery): array 103 | { 104 | $r = Helper::padToEven($r); 105 | $s = Helper::padToEven($s); 106 | 107 | return [ 108 | 'v' => dechex($recovery + self::V_BITS), 109 | 'r' => $r, 110 | 's' => $s 111 | ]; 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /src/Minter/Library/Helper.php: -------------------------------------------------------------------------------- 1 | $value) { 60 | if (is_array($value)) { 61 | $data[$key] = self::hex2binRecursive($value); 62 | } else if (is_string($value) && ctype_xdigit($value)) { 63 | $data[$key] = hex2bin($value); 64 | } 65 | } 66 | 67 | return $data; 68 | } 69 | 70 | /** 71 | * Remove MinterWallet prefix from address or transaction 72 | * 73 | * @param string $string 74 | * @return string 75 | */ 76 | public static function removeWalletPrefix(string $string): string 77 | { 78 | return self::removePrefix($string, MinterPrefix::ADDRESS); 79 | } 80 | 81 | /** 82 | * Remove prefix 83 | * 84 | * @param string $string 85 | * @param string $prefix 86 | * @return string 87 | */ 88 | public static function removePrefix(string $string, string $prefix): string 89 | { 90 | return substr($string, strlen($prefix)); 91 | } 92 | 93 | /** 94 | * Add MinterWallet prefix to address or transaction 95 | * 96 | * @param string $string 97 | * @return string 98 | */ 99 | public static function addWalletPrefix(string $string): string 100 | { 101 | return MinterPrefix::ADDRESS . $string; 102 | } 103 | 104 | /** 105 | * Remove 0s from the end 106 | * 107 | * @param $number 108 | * @return string 109 | */ 110 | public static function niceNumber($number): string 111 | { 112 | return rtrim(rtrim($number, '0'), '.'); 113 | } 114 | 115 | /** 116 | * Add 0 if length of hex string is odd 117 | * 118 | * @param string $hexString 119 | * @return string 120 | */ 121 | public static function padToEven(string $hexString): string 122 | { 123 | return strlen($hexString) % 2 !== 0 ? '0' . $hexString : $hexString; 124 | } 125 | 126 | /** 127 | * Create Keccak 256 hash 128 | * 129 | * @param array $tx 130 | * @return string 131 | */ 132 | public static function createKeccakHash(string $dataString): string 133 | { 134 | $binaryTx = hex2bin($dataString); 135 | 136 | return Keccak::hash($binaryTx, 256); 137 | } 138 | 139 | /** 140 | * Convert RLP array to hex array 141 | * 142 | * @param string $data 143 | * @return array 144 | */ 145 | public static function hex2rlp(string $data): array 146 | { 147 | $rlp = new RLP(); 148 | $key = 0; 149 | $decoded = $rlp->decode('0x' . $data); 150 | 151 | return array_map(function ($v) use ($rlp, &$key) { 152 | $key++; 153 | return $key == 6 || $key == 10 ? $rlp->decode('0x' . $v) : (string)$v; 154 | }, $decoded); 155 | } 156 | 157 | /** 158 | * Create buffer from data recursively. 159 | * 160 | * @param $data 161 | * @return array|Buffer 162 | */ 163 | public static function hex2buffer($data) 164 | { 165 | if (is_array($data)) { 166 | return array_map(function ($item) { 167 | return self::hex2buffer($item); 168 | }, $data); 169 | } 170 | 171 | return new Buffer($data, 'hex'); 172 | } 173 | 174 | /** 175 | * @param string $str 176 | * @return string 177 | */ 178 | public static function str2hex(string $str): string 179 | { 180 | $str = unpack('H*', $str); 181 | 182 | return array_shift($str); 183 | } 184 | 185 | /** 186 | * @param string $str 187 | * @return Buffer 188 | */ 189 | public static function str2buffer(string $str): Buffer 190 | { 191 | $splitted = str_split($str, 1); 192 | return new Buffer($splitted); 193 | } 194 | 195 | /** 196 | * @param $data 197 | * @return string 198 | */ 199 | public static function base64urlEncode($data): string 200 | { 201 | return rtrim(strtr(base64_encode($data), '+/', '-_'), '='); 202 | } 203 | } 204 | -------------------------------------------------------------------------------- /src/Minter/Library/Http.php: -------------------------------------------------------------------------------- 1 | client = $client; 30 | } 31 | 32 | /** 33 | * http get request 34 | * 35 | * @param string $url 36 | * @param array|null $parameters 37 | * @return mixed 38 | * @throws \Exception 39 | * @throws GuzzleException 40 | */ 41 | protected function get(string $url, array $parameters = null) 42 | { 43 | try { 44 | $response = $this->client->request('GET', $url, [ 45 | 'query' => $parameters 46 | ])->getBody(); 47 | } catch (RequestException $exception) { 48 | throw $exception; 49 | } 50 | 51 | return json_decode($response); 52 | } 53 | 54 | /** 55 | * http post request 56 | * 57 | * @param string $url 58 | * @param array $parameters 59 | * @return mixed 60 | * @throws \Exception 61 | * @throws GuzzleException 62 | */ 63 | protected function post(string $url, array $parameters = []) 64 | { 65 | try { 66 | $response = $this->client->request('POST', $url, [ 67 | 'json' => $parameters 68 | ])->getBody(); 69 | } catch (RequestException $exception) { 70 | throw $exception; 71 | } 72 | 73 | return json_decode($response); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/Minter/MinterAPI.php: -------------------------------------------------------------------------------- 1 | setClient($node); 35 | } else { 36 | $client = $this->createDefaultHttpClient($node); 37 | $this->setClient($client); 38 | } 39 | } 40 | 41 | /** 42 | * @param string $baseUri 43 | * @return Client 44 | */ 45 | public function createDefaultHttpClient(string $baseUri): Client 46 | { 47 | return new Client([ 48 | 'base_uri' => $baseUri, 49 | 'connect_timeout' => self::HTTP_DEFAULT_CONNECT_TIMEOUT, 50 | 'timeout' => self::HTTP_DEFAULT_TIMEOUT, 51 | 'verify' => false 52 | ]); 53 | } 54 | 55 | /** 56 | * Get status of node 57 | * 58 | * @return \stdClass 59 | * @throws Exception 60 | * @throws GuzzleException 61 | */ 62 | public function getStatus(): \stdClass 63 | { 64 | return $this->get('status'); 65 | } 66 | 67 | /** 68 | * This endpoint shows candidate’s info by provided public_key. 69 | * It will respond with 404 code if candidate is not found. 70 | * 71 | * @param string $publicKey 72 | * @param null|int $height 73 | * @return \stdClass 74 | * @throws Exception 75 | * @throws GuzzleException 76 | */ 77 | public function getCandidate(string $publicKey, ?int $height = null): \stdClass 78 | { 79 | if ($height) { 80 | $params = ['height' => $height]; 81 | } 82 | 83 | return $this->get('candidate/' . $publicKey, $params ?? null); 84 | } 85 | 86 | /** 87 | * Returns list of active validators 88 | * 89 | * @param null|int $height 90 | * @param int|null $page 91 | * @param int|null $perPage 92 | * @return \stdClass 93 | * @throws GuzzleException 94 | */ 95 | public function getValidators(?int $height = null, ?int $page = 1, ?int $perPage = null): \stdClass 96 | { 97 | $params = ['page' => $page]; 98 | 99 | if ($height) { 100 | $params['height'] = $height; 101 | } 102 | 103 | if ($perPage) { 104 | $params['per_page'] = $perPage; 105 | } 106 | 107 | return $this->get('validators', $params); 108 | } 109 | 110 | /** 111 | * Returns the balance of given account and the number of outgoing transaction. 112 | * 113 | * @param string $address 114 | * @param null|int $height 115 | * @param bool $delegated 116 | * @return \stdClass 117 | * @throws GuzzleException 118 | */ 119 | public function getBalance(string $address, ?int $height = null, bool $delegated = false): \stdClass 120 | { 121 | $params = ['delegated' => $delegated]; 122 | if ($height) { 123 | $params['height'] = $height; 124 | } 125 | 126 | return $this->get('address/' . $address, $params); 127 | } 128 | 129 | /** 130 | * Returns addresses balances. 131 | * 132 | * @param array $addresses 133 | * @param int|null $height 134 | * @param bool $delegated 135 | * @return \stdClass 136 | * @throws GuzzleException 137 | */ 138 | public function getAddresses(array $addresses, ?int $height = null, bool $delegated = false): \stdClass 139 | { 140 | $params = ['addresses' => json_encode($addresses)]; 141 | 142 | if ($height) { 143 | $params['height'] = $height; 144 | } 145 | 146 | return $this->get('addresses', $params); 147 | } 148 | 149 | /** 150 | * Returns nonce. 151 | * 152 | * @param string $address 153 | * @return int 154 | * @throws Exception 155 | * @throws GuzzleException 156 | */ 157 | public function getNonce(string $address): int 158 | { 159 | return $this->getBalance($address)->transaction_count + 1; 160 | } 161 | 162 | /** 163 | * Sends transaction to the Minter Network. 164 | * 165 | * @param string $tx 166 | * @return \stdClass 167 | * @throws Exception 168 | * @throws GuzzleException 169 | */ 170 | public function send(string $tx): \stdClass 171 | { 172 | return $this->post('send_transaction', ['tx' => $tx]); 173 | } 174 | 175 | /** 176 | * Returns transaction info. 177 | * 178 | * @param string $hash 179 | * @return \stdClass 180 | * @throws Exception 181 | * @throws GuzzleException 182 | */ 183 | public function getTransaction(string $hash): \stdClass 184 | { 185 | return $this->get('transaction/' . $hash); 186 | } 187 | 188 | /** 189 | * @param int $height 190 | * @param bool|null $failedTxs 191 | * @return \stdClass 192 | * @throws GuzzleException 193 | */ 194 | public function getBlock(int $height, ?bool $failedTxs = false): \stdClass 195 | { 196 | return $this->get('block/' . $height, ($failedTxs ? ['failed_txs' => true] : null)); 197 | } 198 | 199 | /** 200 | * Returns events at given height. 201 | * 202 | * @param int $height 203 | * @return \stdClass 204 | * @throws Exception 205 | * @throws GuzzleException 206 | */ 207 | public function getEvents(int $height): \stdClass 208 | { 209 | return $this->get('events/' . $height); 210 | } 211 | 212 | /** 213 | * Returns list of candidates. 214 | * 215 | * @param null|int $height 216 | * @param bool|null $includeStakes 217 | * @param string $status 218 | * @return \stdClass 219 | * @throws GuzzleException 220 | */ 221 | public function getCandidates(?int $height = null, ?bool $includeStakes = false, string $status = 'all'): \stdClass 222 | { 223 | $params = ['status' => $status]; 224 | 225 | if ($includeStakes) { 226 | $params['include_stakes'] = 'true'; 227 | } 228 | 229 | if ($height) { 230 | $params['height'] = $height; 231 | } 232 | 233 | return $this->get('candidates', $params); 234 | } 235 | 236 | /** 237 | * Returns information about coin. 238 | * Note: this method does not return information about base coins (MNT and BIP). 239 | * 240 | * @param null|int $height 241 | * @param string $symbol 242 | * @return \stdClass 243 | * @throws Exception 244 | * @throws GuzzleException 245 | */ 246 | public function getCoinInfo(string $symbol, ?int $height = null): \stdClass 247 | { 248 | if ($height) { 249 | $params['height'] = $height; 250 | } 251 | 252 | return $this->get('coin_info/' . $symbol, $params ?? null); 253 | } 254 | 255 | /** 256 | * Return estimate of sell coin transaction. 257 | * 258 | * @param string $coinToSell 259 | * @param string $valueToSell 260 | * @param string $coinToBuy 261 | * @param null|int $height 262 | * @param string $swapFrom 263 | * @return \stdClass 264 | * @throws Exception 265 | * @throws GuzzleException 266 | */ 267 | public function estimateCoinSell( 268 | string $coinToSell, 269 | string $valueToSell, 270 | string $coinToBuy, 271 | ?int $height = null, 272 | string $swapFrom = 'optimal' 273 | ): \stdClass { 274 | $params = [ 275 | 'coin_to_sell' => $coinToSell, 276 | 'value_to_sell' => $valueToSell, 277 | 'coin_to_buy' => $coinToBuy, 278 | 'swap_from' => $swapFrom 279 | ]; 280 | 281 | if ($height) { 282 | $params['height'] = $height; 283 | } 284 | 285 | return $this->get('estimate_coin_sell', $params); 286 | } 287 | 288 | /** 289 | * Return estimate of sell all coin transaction. 290 | * 291 | * @param string $coinToSell 292 | * @param string $valueToSell 293 | * @param string $coinToBuy 294 | * @param int|null $height 295 | * @param string $swapFrom 296 | * @return \stdClass 297 | * @throws GuzzleException 298 | */ 299 | public function estimateCoinSellAll( 300 | string $coinToSell, 301 | string $valueToSell, 302 | string $coinToBuy, 303 | ?int $height = null, 304 | string $swapFrom = 'optimal' 305 | ): \stdClass { 306 | $params = [ 307 | 'coin_to_sell' => $coinToSell, 308 | 'value_to_sell' => $valueToSell, 309 | 'coin_to_buy' => $coinToBuy, 310 | 'swap_from' => $swapFrom 311 | ]; 312 | 313 | if ($height) { 314 | $params['height'] = $height; 315 | } 316 | 317 | return $this->get('estimate_coin_sell_all', $params); 318 | } 319 | 320 | /** 321 | * Return estimate of buy coin transaction. 322 | * 323 | * @param string $coinToSell 324 | * @param string $valueToBuy 325 | * @param string $coinToBuy 326 | * @param null|int $height 327 | * @param string $swapFrom 328 | * @return \stdClass 329 | * @throws Exception 330 | * @throws GuzzleException 331 | */ 332 | public function estimateCoinBuy( 333 | string $coinToSell, 334 | string $valueToBuy, 335 | string $coinToBuy, 336 | ?int $height = null, 337 | string $swapFrom = 'optimal' 338 | ): \stdClass { 339 | $params = [ 340 | 'coin_to_sell' => $coinToSell, 341 | 'value_to_buy' => $valueToBuy, 342 | 'coin_to_buy' => $coinToBuy, 343 | 'swap_from' => $swapFrom 344 | 345 | ]; 346 | 347 | if ($height) { 348 | $params['height'] = $height; 349 | } 350 | 351 | return $this->get('estimate_coin_buy', $params); 352 | } 353 | 354 | /** 355 | * Return estimate of transaction. 356 | * 357 | * @param string $tx 358 | * @param int|null $height 359 | * @return \stdClass 360 | * @throws GuzzleException 361 | */ 362 | public function estimateTxCommission(string $tx, ?int $height = null): \stdClass 363 | { 364 | return $this->get('estimate_tx_commission/' . $tx, ($height ? ['height' => $height] : null)); 365 | } 366 | 367 | /** 368 | * Get transactions by query. 369 | * 370 | * @param string $query 371 | * @param int|null $page 372 | * @param int|null $perPage 373 | * @return \stdClass 374 | * @throws Exception 375 | * @throws GuzzleException 376 | */ 377 | public function getTransactions(string $query, ?int $page = null, ?int $perPage = null): \stdClass 378 | { 379 | $params = ['query' => $query]; 380 | 381 | if ($page) { 382 | $params['page'] = $page; 383 | } 384 | 385 | if ($perPage) { 386 | $params['per_page'] = $perPage; 387 | } 388 | 389 | 390 | return $this->get('transactions', $params); 391 | } 392 | 393 | /** 394 | * Returns unconfirmed transactions. 395 | * 396 | * @param int|null $limit 397 | * @return \stdClass 398 | * @throws Exception 399 | * @throws GuzzleException 400 | */ 401 | public function getUnconfirmedTxs(?int $limit = null): \stdClass 402 | { 403 | return $this->get('unconfirmed_txs', ($limit ? ['limit' => $limit] : null)); 404 | } 405 | 406 | /** 407 | * Returns current max gas price. 408 | * 409 | * @param int|null $height 410 | * @return \stdClass 411 | * @throws Exception 412 | * @throws GuzzleException 413 | */ 414 | public function getMaxGasPrice(?int $height = null): \stdClass 415 | { 416 | return $this->get('max_gas', ($height ? ['height' => $height] : null)); 417 | } 418 | 419 | /** 420 | * Returns current min gas price. 421 | * 422 | * @return \stdClass 423 | * @throws Exception 424 | * @throws GuzzleException 425 | */ 426 | public function getMinGasPrice(): \stdClass 427 | { 428 | return $this->get('min_gas_price'); 429 | } 430 | 431 | /** 432 | * Returns missed blocks by validator public key. 433 | * 434 | * @param string $pubKey 435 | * @param int|null $height 436 | * @return \stdClass 437 | * @throws Exception 438 | * @throws GuzzleException 439 | */ 440 | public function getMissedBlocks(string $pubKey, ?int $height = null): \stdClass 441 | { 442 | return $this->get('missed_blocks/' . $pubKey, ($height ? ['height' => $height] : null)); 443 | } 444 | 445 | /** 446 | * Return network genesis. 447 | * 448 | * @return \stdClass 449 | * @throws GuzzleException 450 | */ 451 | public function getGenesis(): \stdClass 452 | { 453 | return $this->get('genesis'); 454 | } 455 | 456 | /** 457 | * Return node network information. 458 | * 459 | * @return \stdClass 460 | * @throws GuzzleException 461 | */ 462 | public function getNetworkInfo(): \stdClass 463 | { 464 | return $this->get('net_info'); 465 | } 466 | 467 | /** 468 | * @param int $id 469 | * @param int|null $height 470 | * @return \stdClass 471 | * @throws GuzzleException 472 | */ 473 | public function getCoinInfoByID(int $id, ?int $height = null): \stdClass 474 | { 475 | return $this->get('coin_info_by_id/' . $id, ($height ? ['height' => $height] : null)); 476 | } 477 | 478 | /** 479 | * @param int|null $height 480 | * @return \stdClass 481 | * @throws GuzzleException 482 | */ 483 | public function getHalts(?int $height = null): \stdClass 484 | { 485 | return $this->get('halts', ($height ? ['height' => $height] : null)); 486 | } 487 | 488 | /** 489 | * @param string|null $address 490 | * @param string|null $coin 491 | * @return \stdClass 492 | */ 493 | public function getFrozen(?string $address = null, ?string $coin = null): \stdClass 494 | { 495 | $params = []; 496 | 497 | if ($address) { 498 | $params['address'] = $address; 499 | } 500 | 501 | if ($coin) { 502 | $params['coin'] = $coin; 503 | } 504 | 505 | return $this->get('frozen', $params); 506 | } 507 | 508 | /** 509 | * @param string $address 510 | * @param string|null $publicKey 511 | * @param int|null $height 512 | * @return \stdClass 513 | * @throws GuzzleException 514 | */ 515 | public function getWaitlist(string $address, ?string $publicKey = null, ?int $height = null): \stdClass 516 | { 517 | $params = []; 518 | 519 | if ($height) { 520 | $params['height'] = $height; 521 | } 522 | 523 | if ($publicKey) { 524 | $params['publicKey'] = $publicKey; 525 | } 526 | 527 | return $this->get('waitlist/' . $address, $params); 528 | } 529 | 530 | /** 531 | * @param int|null $height 532 | * @return \stdClass 533 | * @throws GuzzleException 534 | */ 535 | public function getPriceCommissions(?int $height = null): \stdClass 536 | { 537 | return $this->get('price_commissions', ($height ? ['height' => $height] : null)); 538 | } 539 | 540 | /** 541 | * @param int $height 542 | * @return \stdClass 543 | * @throws GuzzleException 544 | */ 545 | public function getPriceVotes(int $height): \stdClass 546 | { 547 | return $this->get('price_votes/' . $height); 548 | } 549 | 550 | /** 551 | * @param string $coin0 552 | * @param string $coin1 553 | * @param int|null $height 554 | * @return \stdClass 555 | * @throws GuzzleException 556 | */ 557 | public function getSwapPool(string $coin0, string $coin1, ?int $height = null): \stdClass 558 | { 559 | return $this->get('swap_pool/' . $coin0 . '/' . $coin1, ($height ? ['height' => $height] : null)); 560 | } 561 | 562 | /** 563 | * @param string $coin0 564 | * @param string $coin1 565 | * @param string $provider 566 | * @param int|null $height 567 | * @return \stdClass 568 | * @throws GuzzleException 569 | */ 570 | public function getSwapPoolProvider(string $coin0, string $coin1, string $provider, ?int $height = null): \stdClass 571 | { 572 | return $this->get('swap_pool/' . $coin0 . '/' . $coin1 . '/' . $provider, ($height ? ['height' => $height] : null)); 573 | } 574 | 575 | /** 576 | * @param array $ids 577 | * @param int|null $height 578 | * @return \stdClass 579 | * @throws GuzzleException 580 | */ 581 | public function getLimitOrders(array $ids, ?int $height = null): \stdClass 582 | { 583 | $params = ['ids' => $ids]; 584 | if ($height) { 585 | $params['height'] = $height; 586 | } 587 | 588 | return $this->get('limit_orders', $params); 589 | } 590 | 591 | /** 592 | * @param int $limitOrderId 593 | * @param int|null $height 594 | * @return \stdClass 595 | * @throws GuzzleException 596 | */ 597 | public function getLimitOrder(int $limitOrderId, ?int $height = null): \stdClass 598 | { 599 | return $this->get('limit_order/' . $limitOrderId, ($height ? ['height' => $height] : null)); 600 | } 601 | 602 | /** 603 | * @param string $sellCoin 604 | * @param string $buyCoin 605 | * @param int|null $limit 606 | * @param int|null $height 607 | * @return \stdClass 608 | * @throws GuzzleException 609 | */ 610 | public function getLimitOrdersByCoins( 611 | string $sellCoin, 612 | string $buyCoin, 613 | int $limit = null, 614 | ?int $height = null 615 | ): \stdClass { 616 | $params = []; 617 | if ($limit) { 618 | $params['limit'] = $limit; 619 | } 620 | 621 | if ($height) { 622 | $params['height'] = $height; 623 | } 624 | 625 | return $this->get('limit_orders/' . $sellCoin . '/' . $buyCoin, $params); 626 | } 627 | } 628 | -------------------------------------------------------------------------------- /src/Minter/SDK/MinterCheck.php: -------------------------------------------------------------------------------- 1 | rlp = new RLP; 61 | 62 | if(is_array($checkOrAddress)) { 63 | $this->structure = $this->defineProperties($checkOrAddress); 64 | } 65 | 66 | if(is_string($checkOrAddress) && !$passphrase) { 67 | $this->structure = $this->decode($checkOrAddress); 68 | } 69 | else if(is_string($checkOrAddress)) { 70 | $this->minterAddress = $checkOrAddress; 71 | } 72 | 73 | $this->passphrase = $passphrase; 74 | } 75 | 76 | /** 77 | * Get check structure. 78 | * 79 | * @return array 80 | */ 81 | public function getBody(): array 82 | { 83 | return $this->structure; 84 | } 85 | 86 | /** 87 | * Get owner address from decoded check. 88 | * 89 | * @return string 90 | */ 91 | public function getOwnerAddress(): string 92 | { 93 | return $this->minterAddress; 94 | } 95 | 96 | /** 97 | * Sign check. 98 | * 99 | * @param string $privateKey 100 | * @return string 101 | */ 102 | public function sign(string $privateKey): string 103 | { 104 | // create message hash and passphrase by first 4 fields 105 | $msgHash = $this->serialize(array_slice($this->structure, 0, 6)); 106 | 107 | $passphrase = hash('sha256', $this->passphrase); 108 | 109 | // create elliptic curve and sign 110 | $signature = ECDSA::sign($msgHash, $passphrase); 111 | 112 | // define lock field 113 | $this->structure['lock'] = hex2bin($this->formatLockFromSignature($signature)); 114 | 115 | // create message hash with lock field 116 | $msgHashWithLock = $this->serialize(array_slice($this->structure, 0, 7)); 117 | 118 | // create signature 119 | $signature = ECDSA::sign($msgHashWithLock, $privateKey); 120 | $this->structure = array_merge($this->structure, Helper::hex2buffer($signature)); 121 | 122 | // rlp encode data and add Minter wallet prefix 123 | return MinterPrefix::CHECK . $this->rlp->encode($this->structure); 124 | } 125 | 126 | /** 127 | * Create proof by address and passphrase. 128 | * 129 | * @return string 130 | * @throws \Exception 131 | */ 132 | public function createProof(): string 133 | { 134 | if(!$this->minterAddress) { 135 | throw new \Exception('Minter address is not defined'); 136 | } 137 | 138 | // create msg hash of address 139 | $minterAddress = [hex2bin(Helper::removeWalletPrefix($this->minterAddress))]; 140 | $addressHash = $this->serialize($minterAddress); 141 | 142 | // get SHA 256 hash of password and create EC signature 143 | $passphrase = hash('sha256', $this->passphrase); 144 | $signature = ECDSA::sign($addressHash, $passphrase); 145 | 146 | // return formatted proof 147 | return $this->formatLockFromSignature($signature); 148 | } 149 | 150 | /** 151 | * Decode check. 152 | * 153 | * @param string $check 154 | * @return array 155 | */ 156 | protected function decode(string $check): array 157 | { 158 | // prepare check string and convert to hex array 159 | $check = Helper::removePrefix($check, MinterPrefix::CHECK); 160 | $check = $this->rlp->decode('0x' . $check); 161 | 162 | // prepare decoded data 163 | foreach ($check as $key => $value) { 164 | $field = $this->structure[$key]; 165 | 166 | switch ($field) { 167 | case 'nonce': 168 | $data[$field] = Helper::hex2str($value); 169 | break; 170 | 171 | case 'value': 172 | $data[$field] = MinterConverter::convertToBase(Helper::hexDecode($value)); 173 | break; 174 | 175 | default: 176 | $data[$field] = (string) $value; 177 | if(in_array($field, ['dueBlock', 'v', 'chainId', 'coin', 'gasCoin'])) { 178 | $data[$field] = hexdec($value); 179 | } 180 | break; 181 | } 182 | } 183 | 184 | // set owner address 185 | list($body, $signature) = array_chunk($data, 7, true); 186 | $this->setOwnerAddress($body, $signature); 187 | 188 | return $data; 189 | } 190 | 191 | /** 192 | * Set check owner address. 193 | * 194 | * @param array $body 195 | * @param array $signature 196 | */ 197 | protected function setOwnerAddress(array $body, array $signature): void 198 | { 199 | // encode check to rlp 200 | $lock = array_pop($body); 201 | $check = $this->encode($body); 202 | $check['lock'] = hex2bin($lock); 203 | 204 | // create keccak hash from check 205 | $msg = $this->serialize($check); 206 | 207 | // recover public key 208 | $signature = new Signature([ 209 | 'r' => (string) $signature['r'], 210 | 's' => (string) $signature['s'], 211 | 'recoveryParam' => (int) $signature['v'] 212 | ]); 213 | 214 | $publicKey = ECDSA::recover($msg, $signature); 215 | $publicKey = MinterPrefix::PUBLIC_KEY . $publicKey; 216 | 217 | $this->minterAddress = MinterWallet::getAddressFromPublicKey($publicKey); 218 | } 219 | 220 | /** 221 | * Merge input fields with structure. 222 | * 223 | * @param array $check 224 | * @return array 225 | * @throws \Exception 226 | */ 227 | protected function defineProperties(array $check): array 228 | { 229 | $structure = array_flip($this->structure); 230 | 231 | if(!$this->validateFields($check)) { 232 | throw new \Exception('Invalid fields'); 233 | } 234 | 235 | return array_merge($structure, $this->encode($check)); 236 | } 237 | 238 | /** 239 | * Encode input fields. 240 | * 241 | * @param array $check 242 | * @return array 243 | */ 244 | protected function encode(array $check): array 245 | { 246 | return [ 247 | 'nonce' => Helper::hexDecode( 248 | Helper::str2hex($check['nonce']) 249 | ), 250 | 251 | 'chainId' => dechex($check['chainId']), 252 | 253 | 'dueBlock' => $check['dueBlock'], 254 | 255 | 'coin' => dechex($check['coin']), 256 | 257 | 'value' => MinterConverter::convertToPip($check['value']), 258 | 259 | 'gasCoin' => dechex($check['gasCoin']) 260 | ]; 261 | } 262 | 263 | /** 264 | * Create message Keccak hash from structure fields limited by number of fields. 265 | * 266 | * @return array 267 | */ 268 | protected function serialize($data): string 269 | { 270 | // create msg hash with lock field 271 | $msgHash = $this->rlp->encode($data); 272 | 273 | return Helper::createKeccakHash($msgHash); 274 | } 275 | 276 | /** 277 | * Validate that input fields are correct. 278 | * 279 | * @param array $fields 280 | * @return bool 281 | */ 282 | protected function validateFields(array $fields): bool 283 | { 284 | $structure = array_flip($this->structure); 285 | 286 | foreach ($fields as $field => $fieldValue) { 287 | if(!isset($structure[$field])) { 288 | return false; 289 | } 290 | 291 | if($field === 'nonce' && strlen($fieldValue) > 32) { 292 | return false; 293 | } 294 | } 295 | 296 | return true; 297 | } 298 | 299 | /** 300 | * Prepare lock field. 301 | * 302 | * @param array $signature 303 | * @return string 304 | */ 305 | protected function formatLockFromSignature(array $signature): string 306 | { 307 | $r = str_pad($signature['r'], 64, '0', STR_PAD_LEFT); 308 | $s = str_pad($signature['s'], 64, '0', STR_PAD_LEFT); 309 | $recovery = hexdec($signature['v']) === ECDSA::V_BITS ? '00' : '01'; 310 | 311 | return $r . $s. $recovery; 312 | } 313 | } -------------------------------------------------------------------------------- /src/Minter/SDK/MinterCoins/MinterAddLimitOrderTx.php: -------------------------------------------------------------------------------- 1 | coinToSell = $coinToSell; 31 | $this->coinToBuy = $coinToBuy; 32 | $this->valueToSell = $valueToSell; 33 | $this->valueToBuy = $valueToBuy; 34 | } 35 | 36 | /** 37 | * Prepare data for signing 38 | * 39 | * @return array 40 | */ 41 | function encodeData(): array 42 | { 43 | return [ 44 | $this->coinToSell, 45 | MinterConverter::convertToPip($this->valueToSell), 46 | $this->coinToBuy, 47 | MinterConverter::convertToPip($this->valueToBuy) 48 | ]; 49 | } 50 | 51 | function decodeData() 52 | { 53 | $this->coinToSell = hexdec($this->coinToSell); 54 | $this->coinToBuy = hexdec($this->coinToBuy); 55 | $this->valueToSell = MinterConverter::convertToBase(Helper::hexDecode($this->valueToSell)); 56 | $this->valueToBuy = MinterConverter::convertToBase(Helper::hexDecode($this->valueToBuy)); 57 | } 58 | } -------------------------------------------------------------------------------- /src/Minter/SDK/MinterCoins/MinterAddLiquidityTx.php: -------------------------------------------------------------------------------- 1 | coin0 = $coin0; 33 | $this->coin1 = $coin1; 34 | $this->volume0 = $volume0; 35 | $this->maximumVolume1 = $maximumVolume1; 36 | } 37 | 38 | /** 39 | * Prepare data for signing 40 | * 41 | * @return array 42 | */ 43 | function encodeData(): array 44 | { 45 | return [ 46 | $this->coin0, 47 | $this->coin1, 48 | MinterConverter::convertToPip($this->volume0), 49 | MinterConverter::convertToPip($this->maximumVolume1) 50 | ]; 51 | } 52 | 53 | function decodeData() 54 | { 55 | $this->coin0 = hexdec($this->coin0); 56 | $this->coin1 = hexdec($this->coin1); 57 | $this->volume0 = MinterConverter::convertToBase(Helper::hexDecode($this->volume0)); 58 | $this->maximumVolume1 = MinterConverter::convertToBase(Helper::hexDecode($this->maximumVolume1)); 59 | } 60 | } -------------------------------------------------------------------------------- /src/Minter/SDK/MinterCoins/MinterBurnTokenTx.php: -------------------------------------------------------------------------------- 1 | coin = $coin; 28 | $this->value = $value; 29 | } 30 | 31 | /** 32 | * Prepare data for signing 33 | * 34 | * @return array 35 | */ 36 | public function encodeData(): array 37 | { 38 | return [ 39 | $this->coin, 40 | MinterConverter::convertToPip($this->value) 41 | ]; 42 | } 43 | 44 | public function decodeData() 45 | { 46 | $this->coin = hexdec($this->coin); 47 | $this->value = MinterConverter::convertToBase(Helper::hexDecode($this->value)); 48 | } 49 | } -------------------------------------------------------------------------------- /src/Minter/SDK/MinterCoins/MinterBuyCoinTx.php: -------------------------------------------------------------------------------- 1 | coinToBuy = $coinToBuy; 32 | $this->coinToSell = $coinToSell; 33 | $this->valueToBuy = $valueToBuy; 34 | $this->maximumValueToSell = $maximumValueToSell; 35 | } 36 | 37 | public function encodeData(): array 38 | { 39 | return [ 40 | $this->coinToBuy, 41 | MinterConverter::convertToPip($this->valueToBuy), 42 | $this->coinToSell, 43 | MinterConverter::convertToPip($this->maximumValueToSell) 44 | ]; 45 | } 46 | 47 | public function decodeData() 48 | { 49 | $this->coinToBuy = hexdec($this->coinToBuy); 50 | $this->valueToBuy = MinterConverter::convertToBase(Helper::hexDecode($this->valueToBuy)); 51 | $this->coinToSell = hexdec($this->coinToSell); 52 | $this->maximumValueToSell = MinterConverter::convertToBase(Helper::hexDecode($this->maximumValueToSell)); 53 | } 54 | } -------------------------------------------------------------------------------- /src/Minter/SDK/MinterCoins/MinterBuySwapPoolTx.php: -------------------------------------------------------------------------------- 1 | coins = $coins; 31 | $this->valueToBuy = $valueToBuy; 32 | $this->maximumValueToSell = $maximumValueToSell; 33 | } 34 | 35 | public function encodeData(): array 36 | { 37 | return [ 38 | $this->coins, 39 | MinterConverter::convertToPip($this->valueToBuy), 40 | MinterConverter::convertToPip($this->maximumValueToSell) 41 | ]; 42 | } 43 | 44 | public function decodeData() 45 | { 46 | $this->valueToBuy = MinterConverter::convertToBase(Helper::hexDecode($this->valueToBuy)); 47 | $this->maximumValueToSell = MinterConverter::convertToBase(Helper::hexDecode($this->maximumValueToSell)); 48 | $this->coins = array_map(function ($value) { 49 | return hexdec($value); 50 | }, $this->coins); 51 | } 52 | } -------------------------------------------------------------------------------- /src/Minter/SDK/MinterCoins/MinterCoinTx.php: -------------------------------------------------------------------------------- 1 | MinterSendCoinTx::class, 17 | MinterSellCoinTx::TYPE => MinterSellCoinTx::class, 18 | MinterSellAllCoinTx::TYPE => MinterSellAllCoinTx::class, 19 | MinterBuyCoinTx::TYPE => MinterBuyCoinTx::class, 20 | MinterCreateCoinTx::TYPE => MinterCreateCoinTx::class, 21 | MinterDeclareCandidacyTx::TYPE => MinterDeclareCandidacyTx::class, 22 | MinterDelegateTx::TYPE => MinterDelegateTx::class, 23 | MinterUnbondTx::TYPE => MinterUnbondTx::class, 24 | MinterRedeemCheckTx::TYPE => MinterRedeemCheckTx::class, 25 | MinterSetCandidateOnTx::TYPE => MinterSetCandidateOnTx::class, 26 | MinterSetCandidateOffTx::TYPE => MinterSetCandidateOffTx::class, 27 | MinterCreateMultisigTx::TYPE => MinterCreateMultisigTx::class, 28 | MinterMultiSendTx::TYPE => MinterMultiSendTx::class, 29 | MinterEditCandidateTx::TYPE => MinterEditCandidateTx::class, 30 | MinterRecreateCoinTx::TYPE => MinterRecreateCoinTx::class, 31 | MinterEditCoinOwnerTx::TYPE => MinterEditCoinOwnerTx::class, 32 | MinterSetHaltBlockTx::TYPE => MinterSetHaltBlockTx::class, 33 | MinterEditMultisigTx::TYPE => MinterEditMultisigTx::class, 34 | MinterEditCandidatePublicKeyTx::TYPE => MinterEditCandidatePublicKeyTx::class, 35 | MinterAddLiquidityTx::TYPE => MinterAddLiquidityTx::class, 36 | MinterRemoveLiquidityTx::TYPE => MinterRemoveLiquidityTx::class, 37 | MinterSellSwapPoolTx::TYPE => MinterSellSwapPoolTx::class, 38 | MinterBuySwapPoolTx::TYPE => MinterBuySwapPoolTx::class, 39 | MinterSellAllSwapPoolTx::TYPE => MinterSellAllSwapPoolTx::class, 40 | MinterEditCandidateCommissionTx::TYPE => MinterEditCandidateCommissionTx::class, 41 | MinterMintTokenTx::TYPE => MinterMintTokenTx::class, 42 | MinterBurnTokenTx::TYPE => MinterBurnTokenTx::class, 43 | MinterCreateTokenTx::TYPE => MinterCreateTokenTx::class, 44 | MinterRecreateTokenTx::TYPE => MinterRecreateTokenTx::class, 45 | MinterPriceCommissionTx::TYPE => MinterPriceCommissionTx::class, 46 | MinterCreateSwapPoolTx::TYPE => MinterCreateSwapPoolTx::class, 47 | MinterAddLimitOrderTx::TYPE => MinterAddLimitOrderTx::class, 48 | MinterRemoveLimitOrderTx::TYPE => MinterRemoveLimitOrderTx::class, 49 | MinterMoveStakeTx::TYPE => MinterMoveStakeTx::class, 50 | MinterLockStakeTx::TYPE => MinterLockStakeTx::class, 51 | MinterLockTx::TYPE => MinterLockTx::class, 52 | MinterVoteUpdateTx::TYPE => MinterVoteUpdateTx::class, 53 | ]; 54 | 55 | /** 56 | * @return int 57 | */ 58 | public function getType(): int 59 | { 60 | return static::TYPE; 61 | } 62 | 63 | /** 64 | * @return Buffer 65 | */ 66 | public function encode(): Buffer 67 | { 68 | $rlp = new RLP(); 69 | return $rlp->encode($this->encodeData()); 70 | } 71 | 72 | /** 73 | * Prepare data tx for signing 74 | * 75 | * @return array 76 | */ 77 | abstract function encodeData(): array; 78 | 79 | /** 80 | * Prepare output tx data 81 | */ 82 | abstract function decodeData(); 83 | } -------------------------------------------------------------------------------- /src/Minter/SDK/MinterCoins/MinterCreateCoinTx.php: -------------------------------------------------------------------------------- 1 | name = $name; 36 | $this->symbol = $symbol; 37 | $this->amount = $amount; 38 | $this->reserve = $reserve; 39 | $this->crr = $crr; 40 | $this->maxSupply = $maxSupply; 41 | } 42 | 43 | /** 44 | * Prepare tx data for signing 45 | * 46 | * @return array 47 | */ 48 | public function encodeData(): array 49 | { 50 | return [ 51 | $this->name, 52 | MinterConverter::convertCoinName($this->symbol), 53 | MinterConverter::convertToPip($this->amount), 54 | MinterConverter::convertToPip($this->reserve), 55 | $this->crr === 0 ? '' : $this->crr, 56 | MinterConverter::convertToPip($this->maxSupply) 57 | ]; 58 | } 59 | 60 | public function decodeData() 61 | { 62 | $this->name = Helper::hex2str($this->name); 63 | $this->symbol = Helper::hex2str($this->symbol); 64 | $this->amount = MinterConverter::convertToBase(Helper::hexDecode($this->amount)); 65 | $this->reserve = MinterConverter::convertToBase(Helper::hexDecode($this->reserve)); 66 | $this->crr = hexdec($this->crr); 67 | $this->maxSupply = MinterConverter::convertToBase(Helper::hexDecode($this->maxSupply)); 68 | } 69 | } -------------------------------------------------------------------------------- /src/Minter/SDK/MinterCoins/MinterCreateMultisigTx.php: -------------------------------------------------------------------------------- 1 | threshold = $threshold; 29 | $this->weights = $weights; 30 | $this->addresses = $addresses; 31 | } 32 | 33 | /** 34 | * Prepare data for signing 35 | * 36 | * @return array 37 | */ 38 | public function encodeData(): array 39 | { 40 | $addresses = []; 41 | foreach ($this->addresses as $address) { 42 | $address = Helper::removeWalletPrefix($address); 43 | $addresses[] = hex2bin($address); 44 | } 45 | 46 | $weights = []; 47 | foreach ($this->weights as $weight) { 48 | $weights[] = $weight === 0 ? '' : $weight; 49 | } 50 | 51 | $threshold = $this->threshold === 0 ? '' : $this->threshold; 52 | 53 | return [ 54 | $threshold, 55 | $weights, 56 | $addresses, 57 | ]; 58 | } 59 | 60 | public function decodeData() 61 | { 62 | $threshold = (int)Helper::hexDecode($this->threshold); 63 | 64 | $weights = []; 65 | foreach ($this->weights as $weight) { 66 | $weights[] = hexdec($weight); 67 | } 68 | 69 | $addresses = []; 70 | foreach ($this->addresses as $address) { 71 | $addresses[] = Helper::addWalletPrefix($address); 72 | } 73 | 74 | $this->threshold = $threshold; 75 | $this->weights = $weights; 76 | $this->addresses = $addresses; 77 | } 78 | } -------------------------------------------------------------------------------- /src/Minter/SDK/MinterCoins/MinterCreateSwapPoolTx.php: -------------------------------------------------------------------------------- 1 | coin0 = $coin0; 33 | $this->coin1 = $coin1; 34 | $this->volume0 = $volume0; 35 | $this->volume1 = $volume1; 36 | } 37 | 38 | /** 39 | * Prepare data for signing 40 | * 41 | * @return array 42 | */ 43 | function encodeData(): array 44 | { 45 | return [ 46 | $this->coin0, 47 | $this->coin1, 48 | MinterConverter::convertToPip($this->volume0), 49 | MinterConverter::convertToPip($this->volume1) 50 | ]; 51 | } 52 | 53 | function decodeData() 54 | { 55 | $this->coin0 = hexdec($this->coin0); 56 | $this->coin1 = hexdec($this->coin1); 57 | $this->volume0 = MinterConverter::convertToBase(Helper::hexDecode($this->volume0)); 58 | $this->volume1 = MinterConverter::convertToBase(Helper::hexDecode($this->volume1)); 59 | } 60 | } -------------------------------------------------------------------------------- /src/Minter/SDK/MinterCoins/MinterCreateTokenTx.php: -------------------------------------------------------------------------------- 1 | name = $name; 36 | $this->symbol = $symbol; 37 | $this->initialAmount = $initialAmount; 38 | $this->maxSupply = $maxSupply; 39 | $this->mintable = $mintable; 40 | $this->burnable = $burnable; 41 | } 42 | 43 | /** 44 | * Prepare tx data for signing 45 | * 46 | * @return array 47 | */ 48 | public function encodeData(): array 49 | { 50 | return [ 51 | $this->name, 52 | MinterConverter::convertCoinName($this->symbol), 53 | MinterConverter::convertToPip($this->initialAmount), 54 | MinterConverter::convertToPip($this->maxSupply), 55 | (int) $this->mintable, 56 | (int) $this->burnable 57 | ]; 58 | } 59 | 60 | public function decodeData() 61 | { 62 | $this->name = Helper::hex2str($this->name); 63 | $this->symbol = Helper::hex2str($this->symbol); 64 | $this->initialAmount = MinterConverter::convertToBase(Helper::hexDecode($this->initialAmount)); 65 | $this->maxSupply = MinterConverter::convertToBase(Helper::hexDecode($this->maxSupply)); 66 | $this->mintable = (bool) hexdec($this->mintable); 67 | $this->burnable = (bool) hexdec($this->burnable); 68 | } 69 | } -------------------------------------------------------------------------------- /src/Minter/SDK/MinterCoins/MinterDeclareCandidacyTx.php: -------------------------------------------------------------------------------- 1 | address = $address; 35 | $this->publicKey = $publicKey; 36 | $this->commission = $commission; 37 | $this->coin = $coin; 38 | $this->stake = $stake; 39 | } 40 | 41 | /** 42 | * Prepare data for signing 43 | * 44 | * @return array 45 | */ 46 | public function encodeData(): array 47 | { 48 | return [ 49 | hex2bin(Helper::removeWalletPrefix($this->address)), 50 | hex2bin(Helper::removePrefix($this->publicKey, MinterPrefix::PUBLIC_KEY)), 51 | $this->commission === 0 ? '' : $this->commission, 52 | $this->coin, 53 | MinterConverter::convertToPip($this->stake) 54 | ]; 55 | } 56 | 57 | public function decodeData() 58 | { 59 | $this->address = Helper::addWalletPrefix($this->address); 60 | $this->publicKey = MinterPrefix::PUBLIC_KEY . $this->publicKey; 61 | $this->commission = (int) Helper::hexDecode($this->commission); 62 | $this->coin = hexdec($this->coin); 63 | $this->stake = MinterConverter::convertToBase(Helper::hexDecode($this->stake)); 64 | } 65 | } -------------------------------------------------------------------------------- /src/Minter/SDK/MinterCoins/MinterDelegateTx.php: -------------------------------------------------------------------------------- 1 | publicKey = $publicKey; 31 | $this->coin = $coin; 32 | $this->stake = $stake; 33 | } 34 | 35 | /** 36 | * Prepare data for signing 37 | * 38 | * @return array 39 | */ 40 | public function encodeData(): array 41 | { 42 | return [ 43 | hex2bin(Helper::removePrefix($this->publicKey, MinterPrefix::PUBLIC_KEY)), 44 | $this->coin, 45 | MinterConverter::convertToPip($this->stake) 46 | ]; 47 | } 48 | 49 | public function decodeData() 50 | { 51 | $this->publicKey = MinterPrefix::PUBLIC_KEY . $this->publicKey; 52 | $this->coin = hexdec($this->coin); 53 | $this->stake = MinterConverter::convertToBase(Helper::hexDecode($this->stake)); 54 | } 55 | } -------------------------------------------------------------------------------- /src/Minter/SDK/MinterCoins/MinterEditCandidateCommissionTx.php: -------------------------------------------------------------------------------- 1 | publicKey = $publicKey; 29 | $this->commission = $commission; 30 | } 31 | 32 | /** 33 | * Prepare data for signing 34 | * 35 | * @return array 36 | */ 37 | public function encodeData(): array 38 | { 39 | return [ 40 | hex2bin(Helper::removePrefix($this->publicKey, MinterPrefix::PUBLIC_KEY)), 41 | $this->commission === 0 ? '' : $this->commission 42 | ]; 43 | } 44 | 45 | public function decodeData() 46 | { 47 | $this->publicKey = MinterPrefix::PUBLIC_KEY . $this->publicKey; 48 | $this->commission = (int) Helper::hexDecode($this->commission); 49 | } 50 | } -------------------------------------------------------------------------------- /src/Minter/SDK/MinterCoins/MinterEditCandidatePublicKeyTx.php: -------------------------------------------------------------------------------- 1 | publicKey = $publicKey; 28 | $this->newPublicKey = $newPublicKey; 29 | } 30 | 31 | /** 32 | * Prepare data for signing 33 | * 34 | * @return array 35 | */ 36 | public function encodeData(): array 37 | { 38 | return [ 39 | hex2bin(Helper::removePrefix($this->publicKey, MinterPrefix::PUBLIC_KEY)), 40 | hex2bin(Helper::removePrefix($this->newPublicKey, MinterPrefix::PUBLIC_KEY)), 41 | ]; 42 | } 43 | 44 | public function decodeData() 45 | { 46 | $this->publicKey = MinterPrefix::PUBLIC_KEY . $this->publicKey; 47 | $this->newPublicKey = MinterPrefix::PUBLIC_KEY . $this->newPublicKey; 48 | } 49 | } -------------------------------------------------------------------------------- /src/Minter/SDK/MinterCoins/MinterEditCandidateTx.php: -------------------------------------------------------------------------------- 1 | publicKey = $publicKey; 32 | $this->rewardAddress = $rewardAddress; 33 | $this->ownerAddress = $ownerAddress; 34 | $this->controlAddress = $controlAddress; 35 | } 36 | 37 | /** 38 | * Prepare data for signing 39 | * 40 | * @return array 41 | */ 42 | public function encodeData(): array 43 | { 44 | return [ 45 | hex2bin(Helper::removePrefix($this->publicKey, MinterPrefix::PUBLIC_KEY)), 46 | hex2bin(Helper::removeWalletPrefix($this->rewardAddress)), 47 | hex2bin(Helper::removeWalletPrefix($this->ownerAddress)), 48 | hex2bin(Helper::removeWalletPrefix($this->controlAddress)) 49 | ]; 50 | } 51 | 52 | public function decodeData() 53 | { 54 | $this->publicKey = MinterPrefix::PUBLIC_KEY . $this->publicKey; 55 | $this->rewardAddress = Helper::addWalletPrefix($this->rewardAddress); 56 | $this->ownerAddress = Helper::addWalletPrefix($this->ownerAddress); 57 | $this->controlAddress = Helper::addWalletPrefix($this->controlAddress); 58 | } 59 | } -------------------------------------------------------------------------------- /src/Minter/SDK/MinterCoins/MinterEditCoinOwnerTx.php: -------------------------------------------------------------------------------- 1 | symbol = $symbol; 28 | $this->newOwner = $newOwner; 29 | } 30 | 31 | /** 32 | * Prepare tx data for signing 33 | * 34 | * @return array 35 | */ 36 | public function encodeData(): array 37 | { 38 | return [ 39 | MinterConverter::convertCoinName($this->symbol), 40 | hex2bin(Helper::removeWalletPrefix($this->newOwner)), 41 | ]; 42 | } 43 | 44 | public function decodeData() 45 | { 46 | $this->symbol = Helper::hex2str($this->symbol); 47 | $this->newOwner = Helper::addWalletPrefix($this->newOwner); 48 | } 49 | } -------------------------------------------------------------------------------- /src/Minter/SDK/MinterCoins/MinterEditMultisigTx.php: -------------------------------------------------------------------------------- 1 | threshold = $threshold; 29 | $this->weights = $weights; 30 | $this->addresses = $addresses; 31 | } 32 | 33 | /** 34 | * Prepare tx data for signing 35 | * 36 | * @return array 37 | */ 38 | public function encodeData(): array 39 | { 40 | $addresses = []; 41 | foreach ($this->addresses as $address) { 42 | $address = Helper::removeWalletPrefix($address); 43 | $addresses[] = hex2bin($address); 44 | } 45 | 46 | $weights = []; 47 | foreach ($this->weights as $weight) { 48 | $weights[] = $weight === 0 ? '' : $weight; 49 | } 50 | 51 | $threshold = $this->threshold === 0 ? '' : $this->threshold; 52 | 53 | return [ 54 | $threshold, 55 | $weights, 56 | $addresses 57 | ]; 58 | } 59 | 60 | public function decodeData() 61 | { 62 | $threshold = hexdec($this->threshold); 63 | 64 | $weights = []; 65 | foreach ($this->weights as $weight) { 66 | $weights[] = hexdec($weight); 67 | } 68 | 69 | $addresses = []; 70 | foreach ($this->addresses as $address) { 71 | $addresses[] = Helper::addWalletPrefix($address); 72 | } 73 | 74 | $this->threshold = $threshold; 75 | $this->weights = $weights; 76 | $this->addresses = $addresses; 77 | } 78 | } -------------------------------------------------------------------------------- /src/Minter/SDK/MinterCoins/MinterLockStakeTx.php: -------------------------------------------------------------------------------- 1 | dueBlock = $dueBlock; 29 | $this->coin = $coin; 30 | $this->value = $value; 31 | } 32 | 33 | /** 34 | * Prepare data for signing 35 | * 36 | * @return array 37 | */ 38 | function encodeData(): array 39 | { 40 | return [ 41 | $this->dueBlock, 42 | $this->coin, 43 | MinterConverter::convertToPip($this->value), 44 | ]; 45 | } 46 | 47 | function decodeData() 48 | { 49 | $this->dueBlock = hexdec($this->dueBlock); 50 | $this->coin = hexdec($this->coin); 51 | $this->value = MinterConverter::convertToBase(Helper::hexDecode($this->value)); 52 | } 53 | } -------------------------------------------------------------------------------- /src/Minter/SDK/MinterCoins/MinterMintTokenTx.php: -------------------------------------------------------------------------------- 1 | coin = $coin; 28 | $this->value = $value; 29 | } 30 | 31 | /** 32 | * Prepare data for signing 33 | * 34 | * @return array 35 | */ 36 | public function encodeData(): array 37 | { 38 | return [ 39 | $this->coin, 40 | MinterConverter::convertToPip($this->value) 41 | ]; 42 | } 43 | 44 | public function decodeData() 45 | { 46 | $this->coin = hexdec($this->coin); 47 | $this->value = MinterConverter::convertToBase(Helper::hexDecode($this->value)); 48 | } 49 | } -------------------------------------------------------------------------------- /src/Minter/SDK/MinterCoins/MinterMoveStakeTx.php: -------------------------------------------------------------------------------- 1 | fromPubKey = $fromPubKey; 32 | $this->toPubKey = $toPubKey; 33 | $this->coin = $coin; 34 | $this->value = $value; 35 | } 36 | 37 | /** 38 | * Prepare data for signing 39 | * 40 | * @return array 41 | */ 42 | function encodeData(): array 43 | { 44 | return [ 45 | hex2bin(Helper::removePrefix($this->fromPubKey, MinterPrefix::PUBLIC_KEY)), 46 | hex2bin(Helper::removePrefix($this->toPubKey, MinterPrefix::PUBLIC_KEY)), 47 | $this->coin, 48 | MinterConverter::convertToPip($this->value), 49 | ]; 50 | } 51 | 52 | function decodeData() 53 | { 54 | $this->fromPubKey = MinterPrefix::PUBLIC_KEY . $this->fromPubKey; 55 | $this->toPubKey = MinterPrefix::PUBLIC_KEY . $this->toPubKey; 56 | $this->coin = hexdec($this->coin); 57 | $this->value = MinterConverter::convertToBase(Helper::hexDecode($this->value)); 58 | } 59 | } -------------------------------------------------------------------------------- /src/Minter/SDK/MinterCoins/MinterMultiSendTx.php: -------------------------------------------------------------------------------- 1 | list = $list; 24 | } 25 | 26 | /** 27 | * Prepare tx data for signing 28 | * 29 | * @return array 30 | */ 31 | public function encodeData(): array 32 | { 33 | $list = ['list' => []]; 34 | 35 | foreach ($this->list as $key => $data) { 36 | /** @var $data MinterSendCoinTx */ 37 | $list['list'][$key] = $data->encodeData(); 38 | } 39 | 40 | return $list; 41 | } 42 | 43 | public function decodeData() 44 | { 45 | foreach ($this->list as $key => $data) { 46 | $send = new MinterSendCoinTx(...$data); 47 | $send->decodeData(); 48 | 49 | $this->list[$key] = $send; 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /src/Minter/SDK/MinterCoins/MinterPriceCommissionTx.php: -------------------------------------------------------------------------------- 1 | pubKey = $pubKey; 159 | $this->height = $height; 160 | $this->coin = $coin; 161 | $this->payloadByte = $payloadByte; 162 | $this->send = $send; 163 | $this->buyBancor = $buyBancor; 164 | $this->sellBancor = $sellBancor; 165 | $this->sellAllBancor = $sellAllBancor; 166 | $this->buyPoolBase = $buyPoolBase; 167 | $this->buyPoolDelta = $buyPoolDelta; 168 | $this->sellPoolBase = $sellPoolBase; 169 | $this->sellPoolDelta = $sellPoolDelta; 170 | $this->sellAllPoolBase = $sellAllPoolBase; 171 | $this->sellAllPoolDelta = $sellAllPoolDelta; 172 | $this->createTicker3 = $createTicker3; 173 | $this->createTicker4 = $createTicker4; 174 | $this->createTicker5 = $createTicker5; 175 | $this->createTicker6 = $createTicker6; 176 | $this->createTicker7to10 = $createTicker7to10; 177 | $this->createCoin = $createCoin; 178 | $this->createToken = $createToken; 179 | $this->recreateCoin = $recreateCoin; 180 | $this->recreateToken = $recreateToken; 181 | $this->declareCandidacy = $declareCandidacy; 182 | $this->delegate = $delegate; 183 | $this->unbond = $unbond; 184 | $this->redeemCheck = $redeemCheck; 185 | $this->setCandidateOn = $setCandidateOn; 186 | $this->setCandidateOff = $setCandidateOff; 187 | $this->createMultisig = $createMultisig; 188 | $this->multisendBase = $multisendBase; 189 | $this->multisendDelta = $multisendDelta; 190 | $this->editCandidate = $editCandidate; 191 | $this->setHaltBlock = $setHaltBlock; 192 | $this->editTickerOwner = $editTickerOwner; 193 | $this->editMultisig = $editMultisig; 194 | $this->editCandidatePublicKey = $editCandidatePublicKey; 195 | $this->createSwapPool = $createSwapPool; 196 | $this->addLiquidity = $addLiquidity; 197 | $this->removeLiquidity = $removeLiquidity; 198 | $this->editCandidateCommission = $editCandidateCommission; 199 | $this->burnToken = $burnToken; 200 | $this->mintToken = $mintToken; 201 | $this->voteCommission = $voteCommission; 202 | $this->voteUpdate = $voteUpdate; 203 | } 204 | 205 | /** 206 | * Prepare tx data for signing 207 | * 208 | * @return array 209 | */ 210 | function encodeData(): array 211 | { 212 | return [ 213 | hex2bin(Helper::removePrefix($this->pubKey, MinterPrefix::PUBLIC_KEY)), 214 | $this->height, 215 | $this->coin, 216 | MinterConverter::convertToPip($this->payloadByte), 217 | MinterConverter::convertToPip($this->send), 218 | MinterConverter::convertToPip($this->buyBancor), 219 | MinterConverter::convertToPip($this->sellBancor), 220 | MinterConverter::convertToPip($this->sellAllBancor), 221 | MinterConverter::convertToPip($this->buyPoolBase), 222 | MinterConverter::convertToPip($this->buyPoolDelta), 223 | MinterConverter::convertToPip($this->sellPoolBase), 224 | MinterConverter::convertToPip($this->sellPoolDelta), 225 | MinterConverter::convertToPip($this->sellAllPoolBase), 226 | MinterConverter::convertToPip($this->sellAllPoolDelta), 227 | MinterConverter::convertToPip($this->createTicker3), 228 | MinterConverter::convertToPip($this->createTicker4), 229 | MinterConverter::convertToPip($this->createTicker5), 230 | MinterConverter::convertToPip($this->createTicker6), 231 | MinterConverter::convertToPip($this->createTicker7to10), 232 | MinterConverter::convertToPip($this->createCoin), 233 | MinterConverter::convertToPip($this->createToken), 234 | MinterConverter::convertToPip($this->recreateCoin), 235 | MinterConverter::convertToPip($this->recreateToken), 236 | MinterConverter::convertToPip($this->declareCandidacy), 237 | MinterConverter::convertToPip($this->delegate), 238 | MinterConverter::convertToPip($this->unbond), 239 | MinterConverter::convertToPip($this->redeemCheck), 240 | MinterConverter::convertToPip($this->setCandidateOn), 241 | MinterConverter::convertToPip($this->setCandidateOff), 242 | MinterConverter::convertToPip($this->createMultisig), 243 | MinterConverter::convertToPip($this->multisendBase), 244 | MinterConverter::convertToPip($this->multisendDelta), 245 | MinterConverter::convertToPip($this->editCandidate), 246 | MinterConverter::convertToPip($this->setHaltBlock), 247 | MinterConverter::convertToPip($this->editTickerOwner), 248 | MinterConverter::convertToPip($this->editMultisig), 249 | MinterConverter::convertToPip($this->editCandidatePublicKey), 250 | MinterConverter::convertToPip($this->createSwapPool), 251 | MinterConverter::convertToPip($this->addLiquidity), 252 | MinterConverter::convertToPip($this->removeLiquidity), 253 | MinterConverter::convertToPip($this->editCandidateCommission), 254 | MinterConverter::convertToPip($this->burnToken), 255 | MinterConverter::convertToPip($this->mintToken), 256 | MinterConverter::convertToPip($this->voteCommission), 257 | MinterConverter::convertToPip($this->voteUpdate) 258 | ]; 259 | } 260 | 261 | 262 | function decodeData() 263 | { 264 | $this->pubKey = MinterPrefix::PUBLIC_KEY . $this->pubKey; 265 | $this->height = (int)hexdec($this->height); 266 | $this->coin = hexdec($this->coin); 267 | $this->payloadByte = MinterConverter::convertToBase(Helper::hexDecode($this->payloadByte)); 268 | $this->send = MinterConverter::convertToBase(Helper::hexDecode($this->send)); 269 | $this->buyBancor = MinterConverter::convertToBase(Helper::hexDecode($this->buyBancor)); 270 | $this->sellBancor = MinterConverter::convertToBase(Helper::hexDecode($this->sellBancor)); 271 | $this->sellAllBancor = MinterConverter::convertToBase(Helper::hexDecode($this->sellAllBancor)); 272 | $this->buyPoolBase = MinterConverter::convertToBase(Helper::hexDecode($this->buyPoolBase)); 273 | $this->buyPoolDelta = MinterConverter::convertToBase(Helper::hexDecode($this->buyPoolDelta)); 274 | $this->sellPoolBase = MinterConverter::convertToBase(Helper::hexDecode($this->sellPoolBase)); 275 | $this->sellPoolDelta = MinterConverter::convertToBase(Helper::hexDecode($this->sellPoolDelta)); 276 | $this->sellAllPoolBase = MinterConverter::convertToBase(Helper::hexDecode($this->sellAllPoolBase)); 277 | $this->sellAllPoolDelta = MinterConverter::convertToBase(Helper::hexDecode($this->sellAllPoolDelta)); 278 | $this->createTicker3 = MinterConverter::convertToBase(Helper::hexDecode($this->createTicker3)); 279 | $this->createTicker4 = MinterConverter::convertToBase(Helper::hexDecode($this->createTicker4)); 280 | $this->createTicker5 = MinterConverter::convertToBase(Helper::hexDecode($this->createTicker5)); 281 | $this->createTicker6 = MinterConverter::convertToBase(Helper::hexDecode($this->createTicker6)); 282 | $this->createTicker7to10 = MinterConverter::convertToBase(Helper::hexDecode($this->createTicker7to10)); 283 | $this->createCoin = MinterConverter::convertToBase(Helper::hexDecode($this->createCoin)); 284 | $this->createToken = MinterConverter::convertToBase(Helper::hexDecode($this->createToken)); 285 | $this->recreateCoin = MinterConverter::convertToBase(Helper::hexDecode($this->recreateCoin)); 286 | $this->recreateToken = MinterConverter::convertToBase(Helper::hexDecode($this->recreateToken)); 287 | $this->declareCandidacy = MinterConverter::convertToBase(Helper::hexDecode($this->declareCandidacy)); 288 | $this->delegate = MinterConverter::convertToBase(Helper::hexDecode($this->delegate)); 289 | $this->unbond = MinterConverter::convertToBase(Helper::hexDecode($this->unbond)); 290 | $this->redeemCheck = MinterConverter::convertToBase(Helper::hexDecode($this->redeemCheck)); 291 | $this->setCandidateOn = MinterConverter::convertToBase(Helper::hexDecode($this->setCandidateOn)); 292 | $this->setCandidateOff = MinterConverter::convertToBase(Helper::hexDecode($this->setCandidateOff)); 293 | $this->createMultisig = MinterConverter::convertToBase(Helper::hexDecode($this->createMultisig)); 294 | $this->multisendBase = MinterConverter::convertToBase(Helper::hexDecode($this->multisendBase)); 295 | $this->multisendDelta = MinterConverter::convertToBase(Helper::hexDecode($this->multisendDelta)); 296 | $this->editCandidate = MinterConverter::convertToBase(Helper::hexDecode($this->editCandidate)); 297 | $this->setHaltBlock = MinterConverter::convertToBase(Helper::hexDecode($this->setHaltBlock)); 298 | $this->editTickerOwner = MinterConverter::convertToBase(Helper::hexDecode($this->editTickerOwner)); 299 | $this->editMultisig = MinterConverter::convertToBase(Helper::hexDecode($this->editMultisig)); 300 | $this->editCandidatePublicKey = MinterConverter::convertToBase(Helper::hexDecode($this->editCandidatePublicKey)); 301 | $this->createSwapPool = MinterConverter::convertToBase(Helper::hexDecode($this->createSwapPool)); 302 | $this->addLiquidity = MinterConverter::convertToBase(Helper::hexDecode($this->addLiquidity)); 303 | $this->removeLiquidity = MinterConverter::convertToBase(Helper::hexDecode($this->removeLiquidity)); 304 | $this->editCandidateCommission = MinterConverter::convertToBase(Helper::hexDecode($this->editCandidateCommission)); 305 | $this->burnToken = MinterConverter::convertToBase(Helper::hexDecode($this->burnToken)); 306 | $this->mintToken = MinterConverter::convertToBase(Helper::hexDecode($this->mintToken)); 307 | $this->voteCommission = MinterConverter::convertToBase(Helper::hexDecode($this->voteCommission)); 308 | $this->voteUpdate = MinterConverter::convertToBase(Helper::hexDecode($this->voteUpdate)); 309 | } 310 | } -------------------------------------------------------------------------------- /src/Minter/SDK/MinterCoins/MinterRecreateCoinTx.php: -------------------------------------------------------------------------------- 1 | name = $name; 36 | $this->symbol = $symbol; 37 | $this->amount = $amount; 38 | $this->reserve = $reserve; 39 | $this->crr = $crr; 40 | $this->maxSupply = $maxSupply; 41 | } 42 | 43 | /** 44 | * Prepare tx data for signing 45 | * 46 | * @return array 47 | */ 48 | public function encodeData(): array 49 | { 50 | return [ 51 | $this->name, 52 | MinterConverter::convertCoinName($this->symbol), 53 | MinterConverter::convertToPip($this->amount), 54 | MinterConverter::convertToPip($this->reserve), 55 | $this->crr === 0 ? '' : $this->crr, 56 | MinterConverter::convertToPip($this->maxSupply) 57 | ]; 58 | } 59 | 60 | public function decodeData() 61 | { 62 | $this->name = Helper::hex2str($this->name); 63 | $this->symbol = Helper::hex2str($this->symbol); 64 | $this->amount = MinterConverter::convertToBase(Helper::hexDecode($this->amount)); 65 | $this->reserve = MinterConverter::convertToBase(Helper::hexDecode($this->reserve)); 66 | $this->crr = hexdec($this->crr); 67 | $this->maxSupply = MinterConverter::convertToBase(Helper::hexDecode($this->maxSupply)); 68 | } 69 | } -------------------------------------------------------------------------------- /src/Minter/SDK/MinterCoins/MinterRecreateTokenTx.php: -------------------------------------------------------------------------------- 1 | name = $name; 36 | $this->symbol = $symbol; 37 | $this->initialAmount = $initialAmount; 38 | $this->maxSupply = $maxSupply; 39 | $this->mintable = $mintable; 40 | $this->burnable = $burnable; 41 | } 42 | 43 | /** 44 | * Prepare tx data for signing 45 | * 46 | * @return array 47 | */ 48 | public function encodeData(): array 49 | { 50 | return [ 51 | $this->name, 52 | MinterConverter::convertCoinName($this->symbol), 53 | MinterConverter::convertToPip($this->initialAmount), 54 | MinterConverter::convertToPip($this->maxSupply), 55 | (int) $this->mintable, 56 | (int) $this->burnable 57 | ]; 58 | } 59 | 60 | public function decodeData() 61 | { 62 | $this->name = Helper::hex2str($this->name); 63 | $this->symbol = Helper::hex2str($this->symbol); 64 | $this->initialAmount = MinterConverter::convertToBase(Helper::hexDecode($this->initialAmount)); 65 | $this->maxSupply = MinterConverter::convertToBase(Helper::hexDecode($this->maxSupply)); 66 | $this->mintable = (bool) hexdec($this->mintable); 67 | $this->burnable = (bool) hexdec($this->burnable); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/Minter/SDK/MinterCoins/MinterRedeemCheckTx.php: -------------------------------------------------------------------------------- 1 | check = $check; 28 | $this->proof = $proof; 29 | } 30 | 31 | /** 32 | * Prepare data for signing 33 | * 34 | * @return array 35 | */ 36 | public function encodeData(): array 37 | { 38 | return [ 39 | hex2bin(Helper::removePrefix($this->check, MinterPrefix::CHECK)), 40 | hex2bin($this->proof) 41 | ]; 42 | } 43 | 44 | public function decodeData() 45 | { 46 | $this->check = MinterPrefix::CHECK . $this->check; 47 | $this->proof = (string) $this->proof; 48 | } 49 | } -------------------------------------------------------------------------------- /src/Minter/SDK/MinterCoins/MinterRemoveLimitOrderTx.php: -------------------------------------------------------------------------------- 1 | id = $id; 23 | } 24 | 25 | /** 26 | * Prepare data for signing 27 | * 28 | * @return array 29 | */ 30 | function encodeData(): array 31 | { 32 | return [ 33 | $this->id, 34 | ]; 35 | } 36 | 37 | function decodeData() 38 | { 39 | $this->id = hexdec($this->id); 40 | } 41 | } -------------------------------------------------------------------------------- /src/Minter/SDK/MinterCoins/MinterRemoveLiquidityTx.php: -------------------------------------------------------------------------------- 1 | coin0 = $coin0; 35 | $this->coin1 = $coin1; 36 | $this->liquidity = $liquidity; 37 | $this->minimumVolume0 = $minimumVolume0; 38 | $this->minimumVolume1 = $minimumVolume1; 39 | } 40 | 41 | /** 42 | * Prepare data for signing 43 | * 44 | * @return array 45 | */ 46 | function encodeData(): array 47 | { 48 | return [ 49 | $this->coin0, 50 | $this->coin1, 51 | MinterConverter::convertToPip($this->liquidity), 52 | MinterConverter::convertToPip($this->minimumVolume0), 53 | MinterConverter::convertToPip($this->minimumVolume1) 54 | ]; 55 | } 56 | 57 | function decodeData() 58 | { 59 | $this->coin0 = hexdec($this->coin0); 60 | $this->coin1 = hexdec($this->coin1); 61 | $this->liquidity = MinterConverter::convertToBase(Helper::hexDecode($this->liquidity)); 62 | $this->minimumVolume0 = MinterConverter::convertToBase(Helper::hexDecode($this->minimumVolume0)); 63 | $this->minimumVolume1 = MinterConverter::convertToBase(Helper::hexDecode($this->minimumVolume1)); 64 | } 65 | } -------------------------------------------------------------------------------- /src/Minter/SDK/MinterCoins/MinterSellAllCoinTx.php: -------------------------------------------------------------------------------- 1 | coinToBuy = $coinToBuy; 30 | $this->coinToSell = $coinToSell; 31 | $this->minimumValueToBuy = $minimumValueToBuy; 32 | } 33 | 34 | /** 35 | * Prepare tx data for signing 36 | * 37 | * @return array 38 | */ 39 | public function encodeData(): array 40 | { 41 | return [ 42 | $this->coinToSell, 43 | $this->coinToBuy, 44 | MinterConverter::convertToPip($this->minimumValueToBuy) 45 | ]; 46 | } 47 | 48 | public function decodeData() 49 | { 50 | $this->coinToSell = hexdec($this->coinToSell); 51 | $this->coinToBuy = hexdec($this->coinToBuy); 52 | $this->minimumValueToBuy = MinterConverter::convertToBase(Helper::hexDecode($this->minimumValueToBuy)); 53 | } 54 | } -------------------------------------------------------------------------------- /src/Minter/SDK/MinterCoins/MinterSellAllSwapPoolTx.php: -------------------------------------------------------------------------------- 1 | coins = $coins; 29 | $this->minimumValueToBuy = $minimumValueToBuy; 30 | } 31 | 32 | /** 33 | * Prepare tx data for signing 34 | * 35 | * @return array 36 | */ 37 | public function encodeData(): array 38 | { 39 | return [ 40 | $this->coins, 41 | MinterConverter::convertToPip($this->minimumValueToBuy) 42 | ]; 43 | } 44 | 45 | public function decodeData() 46 | { 47 | $this->minimumValueToBuy = MinterConverter::convertToBase(Helper::hexDecode($this->minimumValueToBuy)); 48 | $this->coins = array_map(function ($value) { 49 | return hexdec($value); 50 | }, $this->coins); 51 | } 52 | } -------------------------------------------------------------------------------- /src/Minter/SDK/MinterCoins/MinterSellCoinTx.php: -------------------------------------------------------------------------------- 1 | coinToBuy = $coinToBuy; 32 | $this->coinToSell = $coinToSell; 33 | $this->valueToSell = $valueToSell; 34 | $this->minimumValueToBuy = $minimumValueToBuy; 35 | } 36 | 37 | /** 38 | * Prepare tx data for signing 39 | * 40 | * @return array 41 | */ 42 | public function encodeData(): array 43 | { 44 | return [ 45 | $this->coinToSell, 46 | MinterConverter::convertToPip($this->valueToSell), 47 | $this->coinToBuy, 48 | MinterConverter::convertToPip($this->minimumValueToBuy) 49 | ]; 50 | } 51 | 52 | public function decodeData() 53 | { 54 | $this->coinToSell = hexdec($this->coinToSell); 55 | $this->valueToSell = MinterConverter::convertToBase(Helper::hexDecode($this->valueToSell)); 56 | $this->coinToBuy = hexdec($this->coinToBuy); 57 | $this->minimumValueToBuy = MinterConverter::convertToBase(Helper::hexDecode($this->minimumValueToBuy)); 58 | } 59 | } -------------------------------------------------------------------------------- /src/Minter/SDK/MinterCoins/MinterSellSwapPoolTx.php: -------------------------------------------------------------------------------- 1 | coins = $coins; 31 | $this->valueToSell = $valueToSell; 32 | $this->minimumValueToBuy = $minimumValueToBuy; 33 | } 34 | 35 | /** 36 | * Prepare tx data for signing 37 | * 38 | * @return array 39 | */ 40 | public function encodeData(): array 41 | { 42 | return [ 43 | $this->coins, 44 | MinterConverter::convertToPip($this->valueToSell), 45 | MinterConverter::convertToPip($this->minimumValueToBuy) 46 | ]; 47 | } 48 | 49 | public function decodeData() 50 | { 51 | $this->valueToSell = MinterConverter::convertToBase(Helper::hexDecode($this->valueToSell)); 52 | $this->minimumValueToBuy = MinterConverter::convertToBase(Helper::hexDecode($this->minimumValueToBuy)); 53 | $this->coins = array_map(function ($value) { 54 | return hexdec($value); 55 | }, $this->coins); 56 | } 57 | } -------------------------------------------------------------------------------- /src/Minter/SDK/MinterCoins/MinterSendCoinTx.php: -------------------------------------------------------------------------------- 1 | coin = $coin; 30 | $this->to = $to; 31 | $this->value = $value; 32 | } 33 | 34 | public function encodeData(): array 35 | { 36 | return [ 37 | $this->coin, 38 | hex2bin(Helper::removeWalletPrefix($this->to)), 39 | MinterConverter::convertToPip($this->value) 40 | ]; 41 | } 42 | 43 | public function decodeData() 44 | { 45 | $this->coin = hexdec($this->coin); 46 | $this->to = Helper::addWalletPrefix($this->to); 47 | $this->value = MinterConverter::convertToBase(Helper::hexDecode($this->value)); 48 | } 49 | } -------------------------------------------------------------------------------- /src/Minter/SDK/MinterCoins/MinterSetCandidateOffTx.php: -------------------------------------------------------------------------------- 1 | publicKey = $publicKey; 26 | } 27 | 28 | /** 29 | * Prepare data for signing 30 | * 31 | * @return array 32 | */ 33 | public function encodeData(): array 34 | { 35 | return [ 36 | hex2bin( 37 | Helper::removePrefix($this->publicKey, MinterPrefix::PUBLIC_KEY) 38 | ), 39 | ]; 40 | } 41 | 42 | public function decodeData() 43 | { 44 | $this->publicKey = MinterPrefix::PUBLIC_KEY . $this->publicKey; 45 | } 46 | } -------------------------------------------------------------------------------- /src/Minter/SDK/MinterCoins/MinterSetCandidateOnTx.php: -------------------------------------------------------------------------------- 1 | publicKey = $publicKey; 26 | } 27 | 28 | /** 29 | * Prepare data for signing 30 | * 31 | * @return array 32 | */ 33 | public function encodeData(): array 34 | { 35 | return [ 36 | hex2bin( 37 | Helper::removePrefix($this->publicKey, MinterPrefix::PUBLIC_KEY) 38 | ), 39 | ]; 40 | } 41 | 42 | public function decodeData() 43 | { 44 | $this->publicKey = MinterPrefix::PUBLIC_KEY . $this->publicKey; 45 | } 46 | } -------------------------------------------------------------------------------- /src/Minter/SDK/MinterCoins/MinterSetHaltBlockTx.php: -------------------------------------------------------------------------------- 1 | publicKey = $publicKey; 28 | $this->height = $height; 29 | } 30 | 31 | /** 32 | * Prepare data for signing 33 | * 34 | * @return array 35 | */ 36 | public function encodeData(): array 37 | { 38 | return [ 39 | hex2bin(Helper::removePrefix($this->publicKey, MinterPrefix::PUBLIC_KEY)), 40 | $this->height, 41 | ]; 42 | } 43 | 44 | public function decodeData() 45 | { 46 | $this->publicKey = MinterPrefix::PUBLIC_KEY . $this->publicKey; 47 | $this->height = (int)hexdec($this->height); 48 | } 49 | } -------------------------------------------------------------------------------- /src/Minter/SDK/MinterCoins/MinterUnbondTx.php: -------------------------------------------------------------------------------- 1 | publicKey = $publicKey; 31 | $this->coin = $coin; 32 | $this->value = $value; 33 | } 34 | 35 | /** 36 | * Prepare data for signing 37 | * 38 | * @return array 39 | */ 40 | public function encodeData(): array 41 | { 42 | return [ 43 | hex2bin(Helper::removePrefix($this->publicKey, MinterPrefix::PUBLIC_KEY)), 44 | $this->coin, 45 | MinterConverter::convertToPip($this->value) 46 | ]; 47 | } 48 | 49 | public function decodeData() 50 | { 51 | $this->publicKey = MinterPrefix::PUBLIC_KEY . $this->publicKey; 52 | $this->coin = hexdec($this->coin); 53 | $this->value = MinterConverter::convertToBase(Helper::hexDecode($this->value)); 54 | } 55 | } -------------------------------------------------------------------------------- /src/Minter/SDK/MinterCoins/MinterVoteUpdateTx.php: -------------------------------------------------------------------------------- 1 | publicKey = $publicKey; 29 | $this->version = $version; 30 | $this->height = $height; 31 | } 32 | 33 | /** 34 | * Prepare data for signing 35 | * 36 | * @return array 37 | */ 38 | public function encodeData(): array 39 | { 40 | return [ 41 | $this->version, 42 | hex2bin(Helper::removePrefix($this->publicKey, MinterPrefix::PUBLIC_KEY)), 43 | $this->height 44 | ]; 45 | } 46 | 47 | public function decodeData() 48 | { 49 | $this->publicKey = MinterPrefix::PUBLIC_KEY . $this->publicKey; 50 | $this->height = hexdec($this->height); 51 | $this->version = Helper::hex2str($this->version); 52 | } 53 | } -------------------------------------------------------------------------------- /src/Minter/SDK/MinterConverter.php: -------------------------------------------------------------------------------- 1 | data = $txData; 50 | $this->rlp = new RLP(); 51 | } 52 | 53 | /** 54 | * @param string $payload 55 | * @return MinterDeepLink 56 | */ 57 | public function setPayload(string $payload): MinterDeepLink 58 | { 59 | $this->payload = $payload; 60 | return $this; 61 | } 62 | 63 | /** 64 | * @param string|int $nonce 65 | * @return MinterDeepLink 66 | */ 67 | public function setNonce($nonce): MinterDeepLink 68 | { 69 | $this->nonce = $nonce; 70 | return $this; 71 | } 72 | 73 | /** 74 | * @param $gasCoin 75 | * @return MinterDeepLink 76 | */ 77 | public function setGasCoin($gasCoin): MinterDeepLink 78 | { 79 | $this->gasCoin = $gasCoin; 80 | return $this; 81 | } 82 | 83 | /** 84 | * @param string|int $gasPrice 85 | * @return MinterDeepLink 86 | */ 87 | public function setGasPrice($gasPrice): MinterDeepLink 88 | { 89 | $this->gasPrice = $gasPrice; 90 | return $this; 91 | } 92 | 93 | /** 94 | * @param string $p 95 | * @return MinterDeepLink 96 | */ 97 | public function setCheckPassword(string $p): MinterDeepLink 98 | { 99 | $this->checkPassword = $p; 100 | return $this; 101 | } 102 | 103 | /** 104 | * @param string $uri 105 | * @return MinterDeepLink 106 | */ 107 | public function setHost(string $uri): MinterDeepLink 108 | { 109 | $this->uri = $uri; 110 | return $this; 111 | } 112 | 113 | /** 114 | * @return string 115 | */ 116 | public function getHost(): string 117 | { 118 | return $this->uri ?? self::LINK_BASE_URL; 119 | } 120 | 121 | /** 122 | * @return string 123 | */ 124 | public function encode(): string 125 | { 126 | $payload = Helper::str2buffer($this->payload ?? ''); 127 | $gasCoin = $this->gasCoin ?? MinterTx::BASE_COIN_ID; 128 | $data = $this->data->encode(); 129 | $txType = $this->data->getType(); 130 | 131 | $deepLink = [ 132 | 'type' => $txType, 133 | 'data' => $data, 134 | 'payload' => $payload, 135 | 'nonce' => $this->nonce, 136 | 'gasPrice' => $this->gasPrice, 137 | 'gasCoin' => $gasCoin 138 | ]; 139 | 140 | $data = $this->rlp->encode($deepLink); 141 | $data = hex2bin($data); 142 | $data = Helper::base64urlEncode($data); 143 | 144 | $url = $this->getHost() . '/' . $data; 145 | if ($this->checkPassword) { 146 | $checkPassword = Helper::str2buffer($this->checkPassword); 147 | $checkPassword = Helper::base64urlEncode($checkPassword); 148 | $url .= "?p=" . $checkPassword; 149 | } 150 | 151 | return $url; 152 | } 153 | } -------------------------------------------------------------------------------- /src/Minter/SDK/MinterPrefix.php: -------------------------------------------------------------------------------- 1 | self::TOTAL_BLOCKS_COUNT) { 47 | return 0; 48 | } 49 | 50 | if($blockNumber === self::TOTAL_BLOCKS_COUNT) { 51 | return self::LAST_REWARD; 52 | } 53 | 54 | $reward = self::formula($blockNumber); 55 | return $reward; 56 | } 57 | 58 | /** 59 | * Calculate reward by formula 60 | * 61 | * @param int $blockNumber 62 | * @return string 63 | */ 64 | protected static function formula(int $blockNumber): string 65 | { 66 | $reward = self::FIRST_REWARD - ($blockNumber / 200000); 67 | 68 | return ceil($reward); 69 | } 70 | } -------------------------------------------------------------------------------- /src/Minter/SDK/MinterSignature.php: -------------------------------------------------------------------------------- 1 | addSingleSignature(...$data); 25 | return; 26 | } 27 | 28 | $this->addMultiSignature(...$data); 29 | } 30 | 31 | /** 32 | * Add single signature 33 | * 34 | * @param string $v 35 | * @param string $r 36 | * @param string $s 37 | */ 38 | public function addSingleSignature(string $v, string $r, string $s) 39 | { 40 | $this->signatures[] = new Signature([ 41 | "r" => $r, 42 | "s" => $s, 43 | "recoveryParam" => hexdec($v) 44 | ]); 45 | } 46 | 47 | /** 48 | * Handle multi-signature 49 | * 50 | * @param string $sender 51 | * @param array $signatures 52 | */ 53 | public function addMultiSignature(string $sender, $signatures) 54 | { 55 | $this->multisigAddress = MinterPrefix::ADDRESS . $sender; 56 | foreach ($signatures as $signature) { 57 | $this->addSingleSignature(...$signature); 58 | } 59 | } 60 | 61 | public function getSignatures(): array 62 | { 63 | return $this->signatures; 64 | } 65 | 66 | public function getMultisigAddress(): string 67 | { 68 | return $this->multisigAddress; 69 | } 70 | } -------------------------------------------------------------------------------- /src/Minter/SDK/MinterTx.php: -------------------------------------------------------------------------------- 1 | setNonce($nonce); 71 | $this->setData($txData); 72 | 73 | if (!$this->getChainID()) { 74 | $this->setChainID(self::MAINNET_CHAIN_ID); 75 | } 76 | 77 | if (!$this->getGasCoin()) { 78 | $this->setGasCoin(self::BASE_COIN_ID); 79 | } 80 | 81 | if (!$this->getGasPrice()) { 82 | $this->setGasPrice(self::DEFAULT_GAS_PRICE); 83 | } 84 | 85 | parent::__construct(); 86 | } 87 | 88 | /** 89 | * Sign tx 90 | * 91 | * @param string $privateKey 92 | * @return string 93 | */ 94 | public function sign(string $privateKey): string 95 | { 96 | $this->setSignatureType(self::SIGNATURE_SINGLE_TYPE); 97 | return MinterPrefix::TRANSACTION . $this->signTransaction($privateKey); 98 | } 99 | 100 | /** 101 | * Sign with multi-signature 102 | * 103 | * @param string $multisigAddress 104 | * @param array $privateKeys 105 | * @return string 106 | */ 107 | public function signMultisig(string $multisigAddress, array $privateKeys): string 108 | { 109 | $this->setSignatureType(self::SIGNATURE_MULTI_TYPE); 110 | return MinterPrefix::TRANSACTION . $this->signTransactionWithMultisig($multisigAddress, $privateKeys); 111 | } 112 | 113 | /** 114 | * @param string $multisigAddress 115 | * @param array $signatures 116 | * @return string 117 | */ 118 | public function signMultisigBySigns(string $multisigAddress, array $signatures): string 119 | { 120 | $this->setSignatureType(self::SIGNATURE_MULTI_TYPE); 121 | return MinterPrefix::TRANSACTION . $this->signTransactionWithSignatures($multisigAddress, $signatures); 122 | } 123 | 124 | /** 125 | * Create transaction signature by private key 126 | * 127 | * @param string $privateKey 128 | * @return string 129 | */ 130 | public function createSignature(string $privateKey): string 131 | { 132 | if ($this->getSignatureType() === null) { 133 | $this->setSignatureType(self::SIGNATURE_SINGLE_TYPE); 134 | } 135 | 136 | return $this->createEncodedSignature($privateKey); 137 | } 138 | 139 | /** 140 | * Get fee of transaction in base coin 141 | * 142 | * @return string 143 | */ 144 | public function getFee(): string 145 | { 146 | // get transaction data fee 147 | $gas = $this->getData()->getFee(); 148 | 149 | if ($this->getGasCoin() !== self::BASE_COIN_ID) { 150 | throw new InvalidArgumentException('Cannot calculate transaction commission with the custom gas coin'); 151 | } 152 | 153 | // multiplied gas price 154 | $gasPrice = bcmul($gas, self::FEE_DEFAULT_MULTIPLIER, 0); 155 | 156 | // commission for payload and serviceData bytes 157 | $commission = bcadd( 158 | strlen($this->payload) * bcmul(self::PAYLOAD_COMMISSION, self::FEE_DEFAULT_MULTIPLIER, 0), 159 | strlen($this->serviceData) * bcmul(self::PAYLOAD_COMMISSION, self::FEE_DEFAULT_MULTIPLIER, 0) 160 | ); 161 | 162 | $fee = bcadd($gasPrice, $commission, 0); 163 | return MinterConverter::convertToBase($fee); 164 | } 165 | 166 | /** 167 | * Decode transaction 168 | * 169 | * @param string $tx 170 | * @return MinterTx 171 | */ 172 | public static function decode(string $tx): MinterTx 173 | { 174 | $data = Helper::hex2rlp($tx); 175 | if (count($data) !== 10) { 176 | throw new InvalidArgumentException('Incorrect transaction raw'); 177 | } 178 | 179 | list($nonce, $chainId, $gasPrice, $gasCoin, $type, $data, $payload, $serviceData, $signatureType, $signatureData) = $data; 180 | 181 | /** @var MinterTxInterface $txData */ 182 | $txData = MinterCoinTx::TYPE_TO_DATA[hexdec($type)]; 183 | $txData = new $txData(...$data); 184 | $txData->decodeData(); 185 | 186 | $tx = new MinterTx(hexdec($nonce), $txData); 187 | $tx->setGasPrice(hexdec($gasPrice)); 188 | $tx->setGasCoin(hexdec($gasCoin)); 189 | $tx->setChainID(hexdec($chainId)); 190 | $tx->setSignatureType(hexdec($signatureType)); 191 | $tx->setPayload(Helper::hex2str($payload)); 192 | $tx->setServiceData(Helper::hex2str($serviceData)); 193 | 194 | $signature = new MinterSignature($tx->getSignatureType(), $signatureData); 195 | $tx->setSignatureData($signature); 196 | 197 | return $tx; 198 | } 199 | 200 | /** 201 | * Get sender Minter address 202 | * 203 | * @return string 204 | */ 205 | public function getSenderAddress(): string 206 | { 207 | if ($this->getSignatureType() === self::SIGNATURE_SINGLE_TYPE) { 208 | return MinterWallet::getAddressFromPublicKey($this->recoverPublicKey()); 209 | } 210 | 211 | return $this->getSignatureData()->getMultisigAddress(); 212 | } 213 | 214 | /** 215 | * @param int $nonce 216 | * @return MinterTx 217 | */ 218 | public function setNonce(int $nonce): MinterTx 219 | { 220 | $this->nonce = $nonce; 221 | return $this; 222 | } 223 | 224 | /** 225 | * @param int $gasPrice 226 | * @return MinterTx 227 | */ 228 | public function setGasPrice(int $gasPrice): MinterTx 229 | { 230 | $this->gasPrice = $gasPrice; 231 | return $this; 232 | } 233 | 234 | /** 235 | * @param int $gasCoin 236 | * @return MinterTx 237 | */ 238 | public function setGasCoin(int $gasCoin): MinterTx 239 | { 240 | $this->gasCoin = $gasCoin; 241 | return $this; 242 | } 243 | 244 | /** 245 | * @param mixed $data 246 | * @return MinterTx 247 | */ 248 | public function setData($data): MinterTx 249 | { 250 | $this->data = $data; 251 | return $this; 252 | } 253 | 254 | /** 255 | * @param int $signatureType 256 | * @return MinterTx 257 | */ 258 | public function setSignatureType(int $signatureType): MinterTx 259 | { 260 | $this->signatureType = $signatureType; 261 | return $this; 262 | } 263 | 264 | /** 265 | * @param MinterSignature $signatureData 266 | * @return MinterTx 267 | */ 268 | public function setSignatureData(MinterSignature $signatureData): MinterTx 269 | { 270 | $this->signatureData = $signatureData; 271 | return $this; 272 | } 273 | 274 | /** 275 | * @param int $chainID 276 | * @return MinterTx 277 | */ 278 | public function setChainID(int $chainID): MinterTx 279 | { 280 | $this->chainID = $chainID; 281 | return $this; 282 | } 283 | 284 | /** 285 | * @return $this 286 | */ 287 | public function setTestnetChainId(): MinterTx 288 | { 289 | $this->chainID = self::TESTNET_CHAIN_ID; 290 | return $this; 291 | } 292 | 293 | /** 294 | * @param mixed $payload 295 | * @return MinterTx 296 | */ 297 | public function setPayload($payload): MinterTx 298 | { 299 | $this->payload = $payload; 300 | return $this; 301 | } 302 | 303 | /** 304 | * @param mixed $serviceData 305 | * @return MinterTx 306 | */ 307 | public function setServiceData($serviceData): MinterTx 308 | { 309 | $this->serviceData = $serviceData; 310 | return $this; 311 | } 312 | 313 | /** 314 | * @return mixed 315 | */ 316 | public function getNonce() 317 | { 318 | return $this->nonce; 319 | } 320 | 321 | /** 322 | * @return mixed 323 | */ 324 | public function getChainID() 325 | { 326 | return $this->chainID; 327 | } 328 | 329 | 330 | /** 331 | * @return mixed 332 | */ 333 | public function getGasCoin() 334 | { 335 | return $this->gasCoin; 336 | } 337 | 338 | /** 339 | * @return mixed 340 | */ 341 | public function getGasPrice() 342 | { 343 | return $this->gasPrice; 344 | } 345 | 346 | /** 347 | * @return mixed 348 | */ 349 | public function getSignatureType() 350 | { 351 | return $this->signatureType; 352 | } 353 | 354 | /** 355 | * @return mixed 356 | */ 357 | public function getServiceData() 358 | { 359 | return $this->serviceData; 360 | } 361 | 362 | /** 363 | * @return mixed 364 | */ 365 | public function getPayload() 366 | { 367 | return $this->payload; 368 | } 369 | 370 | /** 371 | * @return MinterSignature 372 | */ 373 | public function getSignatureData(): MinterSignature 374 | { 375 | return $this->signatureData; 376 | } 377 | 378 | /** 379 | * @return MinterSendCoinTx|MinterBuyCoinTx|MinterSellCoinTx|MinterSellAllCoinTx|MinterDelegateTx|MinterUnbondTx|MinterMultiSendTx|MinterCreateMultisigTx|MinterCreateCoinTx|MinterRecreateCoinTx|MinterEditCoinOwnerTx|MinterDeclareCandidacyTx|MinterSetCandidateOnTx|MinterSetCandidateOffTx|MinterEditCandidateTx|MinterRedeemCheckTx|MinterSetHaltBlockTx|MinterSellSwapPoolTx|MinterSellAllSwapPoolTx|MinterBuySwapPoolTx|MinterPriceCommissionTx|MinterCreateTokenTx|MinterRecreateTokenTx|MinterCreateSwapPoolTx|MinterBurnTokenTx|MinterMintTokenTx|MinterAddLiquidityTx|MinterRemoveLiquidityTx|MinterAddLimitOrderTx|MinterRemoveLimitOrderTx|MinterLockTx|MinterLockStakeTx|MinterMoveStakeTx|MinterVoteUpdateTx 380 | */ 381 | public function getData(): MinterTxInterface 382 | { 383 | return $this->data; 384 | } 385 | } 386 | -------------------------------------------------------------------------------- /src/Minter/SDK/MinterTxSigner.php: -------------------------------------------------------------------------------- 1 | rlp = new RLP(); 40 | } 41 | 42 | /** 43 | * @param string $privateKey 44 | * @return Buffer 45 | */ 46 | public function createEncodedSignature(string $privateKey) 47 | { 48 | $tx = $this->encodeRLP(); 49 | $hash = Helper::createKeccakHash($tx); 50 | $signature = $this->createSignatureByHash($hash, $privateKey); 51 | 52 | return $this->rlp->encode($signature); 53 | } 54 | 55 | /** 56 | * @param string $privateKey 57 | * @return string 58 | */ 59 | protected function signTransaction(string $privateKey): string 60 | { 61 | $tx = $this->encodeRLP(); 62 | $hash = Helper::createKeccakHash($tx); 63 | $signature = $this->createSignatureByHash($hash, $privateKey); 64 | 65 | return $this->encodeRLP($signature); 66 | } 67 | 68 | /** 69 | * @param string $multisigAddress 70 | * @param array $privateKeys 71 | * @return string 72 | */ 73 | protected function signTransactionWithMultisig(string $multisigAddress, array $privateKeys): string 74 | { 75 | $tx = $this->encodeRLP(); 76 | $hash = Helper::createKeccakHash($tx); 77 | 78 | $signatures = []; 79 | foreach ($privateKeys as $privateKey) { 80 | $signatures[] = $this->createSignatureByHash($hash, $privateKey); 81 | } 82 | 83 | return $this->signMultisig($multisigAddress, $signatures); 84 | } 85 | 86 | /** 87 | * @param string $multisigAddress 88 | * @param array $signatures 89 | * @return string 90 | */ 91 | protected function signTransactionWithSignatures(string $multisigAddress, array $signatures): string 92 | { 93 | foreach ($signatures as $key => $signature) { 94 | $signatures[$key] = $this->rlp->decode('0x' . $signature); 95 | } 96 | 97 | return $this->signMultisig($multisigAddress, $signatures); 98 | } 99 | 100 | /** 101 | * Recover sender public key from signature 102 | * 103 | * @return string 104 | */ 105 | protected function recoverPublicKey(): string 106 | { 107 | $tx = $this->encodeRLP(); 108 | $hash = Helper::createKeccakHash($tx); 109 | $signature = $this->signatureData->getSignatures()[0]; 110 | 111 | return MinterPrefix::PUBLIC_KEY . ECDSA::recover($hash, $signature); 112 | } 113 | 114 | /** 115 | * @param string $multisigAddress 116 | * @param array $signatures 117 | * @return string 118 | */ 119 | private function signMultisig(string $multisigAddress, array $signatures): string 120 | { 121 | $multisigAddress = Helper::removeWalletPrefix($multisigAddress); 122 | $multisigAddress = hex2bin($multisigAddress); 123 | 124 | return $this->encodeRLP([$multisigAddress, $signatures]); 125 | } 126 | 127 | /** 128 | * @param string $hash 129 | * @param string $privateKey 130 | * @return array|Buffer 131 | */ 132 | private function createSignatureByHash(string $hash, string $privateKey) 133 | { 134 | $signature = ECDSA::sign($hash, $privateKey); 135 | $signature = Helper::hex2buffer($signature); 136 | return $signature; 137 | } 138 | 139 | /** 140 | * Encode transaction to RLP 141 | * 142 | * @param array|null $signature 143 | * @return Buffer 144 | */ 145 | private function encodeRLP(?array $signature = null): Buffer 146 | { 147 | $tx = [ 148 | $this->nonce, 149 | $this->chainID, 150 | $this->gasPrice, 151 | $this->gasCoin, 152 | $this->data->getType(), 153 | $this->data->encode(), 154 | Helper::str2buffer($this->payload ?? ''), 155 | $this->serviceData ?? '', 156 | $this->signatureType 157 | ]; 158 | 159 | if ($signature) { 160 | $tx[] = $this->rlp->encode($signature); 161 | } 162 | 163 | return $this->rlp->encode($tx); 164 | } 165 | } -------------------------------------------------------------------------------- /src/Minter/SDK/MinterWallet.php: -------------------------------------------------------------------------------- 1 | mnemonic = self::generateMnemonic(); 40 | $this->privateKey = self::mnemonicToPrivateKey($this->mnemonic); 41 | $this->publicKey = self::privateToPublic($this->privateKey); 42 | $this->address = self::getAddressFromPublicKey($this->publicKey); 43 | } 44 | 45 | /** 46 | * Create Minter wallet by private key 47 | * 48 | * @param string $privateKey 49 | * @return MinterWallet 50 | */ 51 | public static function createFromPrivate(string $privateKey): MinterWallet 52 | { 53 | $wallet = new MinterWallet(); 54 | $wallet->privateKey = $privateKey; 55 | $wallet->publicKey = self::privateToPublic($wallet->getPrivateKey()); 56 | $wallet->address = self::getAddressFromPublicKey($wallet->getPublicKey()); 57 | 58 | return $wallet; 59 | } 60 | 61 | /** 62 | * Create Minter wallet by mnemonic phrase 63 | * 64 | * @param string $mnemonic 65 | * @return MinterWallet 66 | */ 67 | public static function createFromMnemonic(string $mnemonic): MinterWallet 68 | { 69 | $wallet = new MinterWallet(); 70 | $wallet->mnemonic = $mnemonic; 71 | $wallet->privateKey = self::mnemonicToPrivateKey($wallet->getMnemonic()); 72 | $wallet->publicKey = self::privateToPublic($wallet->getPrivateKey()); 73 | $wallet->address = self::getAddressFromPublicKey($wallet->getPublicKey()); 74 | 75 | return $wallet; 76 | } 77 | 78 | /** 79 | * Generate public key 80 | * 81 | * @param string $privateKey 82 | * @return string 83 | */ 84 | public static function privateToPublic(string $privateKey): string 85 | { 86 | return MinterPrefix::PUBLIC_KEY . ECDSA::privateToPublic($privateKey); 87 | } 88 | 89 | /** 90 | * Retrieve address from public key 91 | * 92 | * @param string $publicKey 93 | * @return string 94 | */ 95 | public static function getAddressFromPublicKey(string $publicKey): string 96 | { 97 | $publicKey = Helper::removePrefix($publicKey, MinterPrefix::PUBLIC_KEY); 98 | $hash = Keccak::hash(hex2bin($publicKey), 256); 99 | return MinterPrefix::ADDRESS . substr($hash, -40); 100 | } 101 | 102 | /** 103 | * Generate mnemonic phrase from entropy. 104 | * 105 | * @return string 106 | */ 107 | public static function generateMnemonic(): string 108 | { 109 | return BIP39::entropyToMnemonic( 110 | BIP39::generateEntropy(self::BIP44_ENTROPY_BITS) 111 | ); 112 | } 113 | 114 | /** 115 | * Get private key from mnemonic. 116 | * 117 | * @param string $mnemonic 118 | * @return string 119 | */ 120 | public static function mnemonicToPrivateKey(string $mnemonic): string 121 | { 122 | $seed = BIP39::mnemonicToSeedHex($mnemonic, ''); 123 | return BIP44::fromMasterSeed($seed)->derive(self::BIP44_SEED_ADDRESS_PATH)->privateKey; 124 | } 125 | 126 | /** 127 | * Validate that address is valid Minter address 128 | * 129 | * @param string $address 130 | * @return bool 131 | */ 132 | public static function validateAddress(string $address): bool 133 | { 134 | return strlen($address) === 42 && substr($address, 0, 2) === MinterPrefix::ADDRESS && ctype_xdigit(substr($address, -40)); 135 | } 136 | 137 | /** 138 | * @return string 139 | */ 140 | public function getMnemonic(): string 141 | { 142 | return $this->mnemonic; 143 | } 144 | 145 | /** 146 | * @return string 147 | */ 148 | public function getAddress(): string 149 | { 150 | return $this->address; 151 | } 152 | 153 | /** 154 | * @return string 155 | */ 156 | public function getPrivateKey(): string 157 | { 158 | return $this->privateKey; 159 | } 160 | 161 | /** 162 | * @return string 163 | */ 164 | public function getPublicKey(): string 165 | { 166 | return $this->publicKey; 167 | } 168 | } --------------------------------------------------------------------------------