diff --git a/composer.json b/composer.json index 04aae29..c268d23 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,6 @@ { "name": "trustenterprises/hashgraph", - "description": "Laravel package to automatically handle adding trust to any SaaS product", + "description": "Laravel package to integrate with Trust Enterprises Hedera REST API", "keywords": [ "hedera", "hashgraph", diff --git a/src/Http/Client/HashgraphClient.php b/src/Http/Client/HashgraphClient.php index 09b9bde..31ca18a 100644 --- a/src/Http/Client/HashgraphClient.php +++ b/src/Http/Client/HashgraphClient.php @@ -7,8 +7,11 @@ use GuzzleHttp\Exception\GuzzleException; use Trustenterprises\LaravelHashgraph\Contracts\HashgraphConsensus; use Trustenterprises\LaravelHashgraph\Models\AccountCreateResponse; +use Trustenterprises\LaravelHashgraph\Models\AccountTokenBalanceResponse; use Trustenterprises\LaravelHashgraph\Models\BequestToken; use Trustenterprises\LaravelHashgraph\Models\BequestTokenResponse; +use Trustenterprises\LaravelHashgraph\Models\SendTokenResponse; +use Trustenterprises\LaravelHashgraph\Models\SendToken; use Trustenterprises\LaravelHashgraph\Models\ConsensusMessage; use Trustenterprises\LaravelHashgraph\Models\ConsensusMessageResponse; use Trustenterprises\LaravelHashgraph\Models\FungibleToken; @@ -153,4 +156,24 @@ public function bequestToken(BequestToken $bequestToken): BequestTokenResponse return new BequestTokenResponse($data); } + + public function getTokenBalance(string $account_id, string $token_id): AccountTokenBalanceResponse + { + $response = $this->guzzle->get('api/account/' . $account_id . '/' . $token_id); + + $data = json_decode($response->getBody()->getContents())->data; + + return new AccountTokenBalanceResponse($data); + } + + public function sendToken(SendToken $sendToken): SendTokenResponse + { + $response = $this->guzzle->post('api/token/send', [ + 'json' => $sendToken->forRequest(), + ]); + + $data = json_decode($response->getBody()->getContents())->data; + + return new SendTokenResponse($data); + } } diff --git a/src/LaravelHashgraph.php b/src/LaravelHashgraph.php index 45f522f..b202fdd 100644 --- a/src/LaravelHashgraph.php +++ b/src/LaravelHashgraph.php @@ -8,14 +8,18 @@ use Trustenterprises\LaravelHashgraph\Exception\HashgraphException; use Trustenterprises\LaravelHashgraph\Http\Client\HashgraphClient; use Trustenterprises\LaravelHashgraph\Models\AccountCreateResponse; +use Trustenterprises\LaravelHashgraph\Models\AccountTokenBalanceResponse; use Trustenterprises\LaravelHashgraph\Models\BequestToken; use Trustenterprises\LaravelHashgraph\Models\BequestTokenResponse; +use Trustenterprises\LaravelHashgraph\Models\SendTokenResponse; +use Trustenterprises\LaravelHashgraph\Models\SendToken; use Trustenterprises\LaravelHashgraph\Models\ConsensusMessage; use Trustenterprises\LaravelHashgraph\Models\ConsensusMessageResponse; use Trustenterprises\LaravelHashgraph\Models\FungibleToken; use Trustenterprises\LaravelHashgraph\Models\FungibleTokenResponse; use Trustenterprises\LaravelHashgraph\Models\HashgraphTopic; use Trustenterprises\LaravelHashgraph\Models\TopicInfo; +use function Symfony\Component\String\s; class LaravelHashgraph { @@ -96,6 +100,16 @@ public static function createAccount() : AccountCreateResponse return static::withAuthenticatedClient()->getClient()->createAccount(); } + public static function getTokenBalance(string $account_id, string $token_id) : AccountTokenBalanceResponse + { + return static::withAuthenticatedClient()->getClient()->getTokenBalance($account_id, $token_id); + } + + public static function sendToken(SendToken $sendToken) : SendTokenResponse + { + return static::withAuthenticatedClient()->getClient()->sendToken($sendToken); + } + /** * @return TopicInfo * @throws GuzzleException diff --git a/src/Models/AccountTokenBalanceResponse.php b/src/Models/AccountTokenBalanceResponse.php new file mode 100644 index 0000000..a432792 --- /dev/null +++ b/src/Models/AccountTokenBalanceResponse.php @@ -0,0 +1,59 @@ +token_id = $response->token_id; + $this->amount = $response->amount; + $this->decimals = $response->decimals; + $this->raw_amount = $response->raw_amount; + } + + /** + * @return int + */ + public function getAmount(): int + { + return $this->amount; + } + + /** + * @return String + */ + public function getTokenId(): string + { + return $this->token_id; + } + + /** + * @return int + */ + public function getDecimals(): int + { + return $this->decimals; + } + + /** + * @return String + */ + public function getRawAmount(): string + { + return $this->raw_amount; + } +} diff --git a/src/Models/SendToken.php b/src/Models/SendToken.php new file mode 100644 index 0000000..87226c9 --- /dev/null +++ b/src/Models/SendToken.php @@ -0,0 +1,59 @@ +token_id = $token_id; + $this->receiver_id = $receiver_id; + $this->amount = $amount; + } + + public function forRequest(): array + { + return [ + 'token_id' => $this->getTokenId(), + 'receiver_id' => $this->getReceiverId(), + 'amount' => $this->getAmount(), + ]; + } + + /** + * @return string + */ + public function getTokenId(): string + { + return $this->token_id; + } + + /** + * @return string + */ + public function getReceiverId(): string + { + return $this->receiver_id; + } + + /** + * @return string + */ + public function getAmount(): string + { + return $this->amount; + } +} diff --git a/src/Models/SendTokenResponse.php b/src/Models/SendTokenResponse.php new file mode 100644 index 0000000..14fbf61 --- /dev/null +++ b/src/Models/SendTokenResponse.php @@ -0,0 +1,71 @@ +error = $response->error; + } else { + $this->transfer_success = true; + $this->amount = $response->amount; + $this->receiver_id = $response->receiver_id; + $this->transaction_id = $response->transaction_id; + } + } + + /** + * @return bool + */ + public function hasTransferSucceeded(): bool + { + return $this->transfer_success; + } + + /** + * @return String + */ + public function getError(): string + { + return $this->error; + } + + /** + * @return String + */ + public function getAmount(): string + { + return $this->amount; + } + + /** + * @return String + */ + public function getReceiverId(): string + { + return $this->receiver_id; + } + + /** + * @return String + */ + public function getTransactionId(): string + { + return $this->transaction_id; + } +} diff --git a/tests/LaravelHashgraphTest.php b/tests/LaravelHashgraphTest.php index 153ddca..b5c86a7 100644 --- a/tests/LaravelHashgraphTest.php +++ b/tests/LaravelHashgraphTest.php @@ -7,6 +7,7 @@ use Trustenterprises\LaravelHashgraph\Exception\HashgraphException; use Trustenterprises\LaravelHashgraph\LaravelHashgraph; use Trustenterprises\LaravelHashgraph\Models\BequestToken; +use Trustenterprises\LaravelHashgraph\Models\SendToken; use Trustenterprises\LaravelHashgraph\Models\ConsensusMessage; use Trustenterprises\LaravelHashgraph\Models\FungibleToken; use Trustenterprises\LaravelHashgraph\Models\HashgraphTopic; @@ -171,4 +172,70 @@ public function check_that_a_bad_topic_cannot_be_updated() LaravelHashgraph::withTopic(self::TOPIC_NAME)->updateTopic(''); } + + /** + * TODO: These are a set of "dangerous" tests that relies on the node being connected to Hedera testnet and usinga venly wallet. + * + * Checking a wallet balance. + * + * @test + */ + public function check_that_a_venly_balance_is_found() + { + $account_id = '0.0.13283221'; + $token_id = '0.0.15647345'; + + $token_balance = LaravelHashgraph::getTokenBalance($account_id, $token_id); + + $this->assertIsNumeric($token_balance->getAmount()); + $this->assertIsNumeric($token_balance->getDecimals()); + $this->assertIsString($token_balance->getTokenId()); + $this->assertIsString($token_balance->getRawAmount()); + } + + /** + * Sending a token to a venlu wallet. This test will fail one day. 🤪 + * + * @test + */ + public function send_tokens_to_a_venly_wallet() + { + // Pre-generated Venly wallet (testnet) (maxes out at 25 assocs) + $account_id = '0.0.15657776'; // This venly account has these tokens already + $token_id = '0.0.15657534'; // Token already created + $amount = 0.000001; + + $send_token = new SendToken($token_id, $account_id, $amount); + + $token_sent = LaravelHashgraph::sendToken($send_token); + + $this->assertTrue($token_sent->hasTransferSucceeded()); + + // Expect the updated balance of tokens + $token_balance = LaravelHashgraph::getTokenBalance($account_id, $token_id); + + $this->assertNotEmpty($token_balance->getAmount()); + } + + /** + * Attempt to send a token to a full-free-association venlu wallet + * + * @test + */ + public function failed_send_tokens_to_a_full_venly_wallet() + { + // Create a token + $token = new FungibleToken("TEST-NON-ASSOC", "Send token to non-assoc ", "10", "non-assoc transfer test"); + $hashgraph_token = LaravelHashgraph::mintFungibleToken($token); + + // Pre-generated Venly wallet (testnet) (maxes out at 25 assocs) + $account_id = '0.0.13283221'; // This venly account has maxed out auto association + + // Send token object + $send_token = new SendToken($hashgraph_token->getTokenId(), $account_id, 2); + + $token_sent = LaravelHashgraph::sendToken($send_token); + + $this->assertFalse($token_sent->hasTransferSucceeded()); + } }