Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
*.sh text eol=lf
tests/*.sh text eol=lf
5 changes: 3 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
.idea/
vendor/
.idea/
vendor/
tests/.phpunit.result.cache
26 changes: 26 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,28 @@
### 0.7.1

Enhancements and compatibility fixes

- Added `Account::getPaymentOperations($sinceCursor = null, $limit = 50)` which returns only payment-like operations (`payment`, `path_payment`). Use this when you want to ignore `create_account` and `account_merge` records that also appear in Horizon's payments feed. `Account::getPayments()` remains unchanged and returns the heterogeneous feed.
- Standardized amount formatting at Stellar precision (7 decimal places):
- `StellarAmount::getScaledValue()` and `AssetAmount::getBalance()` return strings with 7 decimals.
- `Account::getNativeBalance()` returns a 7-decimal string (e.g., "0.0000000" when empty).
- Stroop accessors return integer strings (no decimals) and are recommended for arithmetic/comparison.
- PHP 8.3 / PHPUnit 9 compatibility:
- Replaced deprecated `@expectedException` annotations with `$this->expectException(...)`.
- `Xdr\\Type\\VariableArray` implements `Countable`.
- Declared `$size` on `Xdr\\XdrBuffer` (no dynamic property).
- Hardened `XdrModel\\Memo` validation to avoid null-related deprecations.
- Horizon behavior resilience:
- `Server::getAccount()` now detects JSON bodies with `status: 404` and returns `null` (previously could throw when certain Horizons didn’t raise exceptions).
- `ApiClient::postTransaction()` throws `PostTransactionException` on non-2xx (4xx) responses even when Guzzle exceptions are disabled.
- Integration test improvements:
- Tests skip gracefully when `STELLAR_HORIZON_BASE_URL` is not set.
- Base class auto-funds core fixtures (`basic1`, `basic2`, `basic3`) via friendbot and polls Horizon to avoid flakiness.
- Environment variables simplified: tests now use only `STELLAR_NETWORK_PASSPHRASE` (deprecated `STELLAR_NETWORK_PASSWORD`).
- Tooling/documentation:
- Normalized shell script line endings (LF) and added `.gitattributes` to enforce.
- README: documented payments feed vs. payment operations, amount formatting/precision, and integration environment setup.

### 0.7.0

* Additional support for BumpSequenceOp: it is now read correctly when listing operations
Expand Down Expand Up @@ -125,3 +150,4 @@ New Features

### 0.1.0
* Initial beta version

42 changes: 21 additions & 21 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
MIT License

Copyright (c) 2017 ZuluCrypto

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
MIT License
Copyright (c) 2017 ZuluCrypto
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
31 changes: 31 additions & 0 deletions RELEASE_NOTES_v0.7.1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
Version 0.7.1 — Enhancements and compatibility fixes

Highlights
- New API: `Account::getPaymentOperations()` returns only payment-like operations (payment, path_payment). Use when you want to ignore create_account and account_merge entries in Horizon’s mixed payments feed. `Account::getPayments()` remains the heterogeneous feed.
- Amount formatting standardized at Stellar precision (7 decimals) across display getters:
- `StellarAmount::getScaledValue()` and `AssetAmount::getBalance()` return 7-decimal strings
- `Account::getNativeBalance()` returns a 7-decimal string (e.g., "0.0000000" when empty)
- Stroop getters return integer strings for storage/comparison
- PHP 8.3 / PHPUnit 9 compatibility and deprecation fixes (Countable, dynamic properties, Memo validation, test annotations).
- Horizon error-handling resilience: JSON 404 handling for getAccount(); `postTransaction()` throws on non-2xx even with Guzzle exceptions disabled.
- Integration test UX: auto-fund core fixtures, graceful skipping; unified env var (`STELLAR_NETWORK_PASSPHRASE`).

Breaking Changes
- None. `Account::getPayments()` remains unchanged; the new method provides a filtered alternative.

Migration Notes
- Prefer `Account::getPaymentOperations()` when you only want payment/path_payment.
- Keep doing arithmetic in stroops (integer strings); use the 7-decimal display methods for presentation.
- Integration tests now expect:
- `STELLAR_HORIZON_BASE_URL` (e.g., http://localhost:8000/)
- `STELLAR_NETWORK_PASSPHRASE` (e.g., Integration Test Network ; zulucrypto)
- Note: `STELLAR_NETWORK_PASSWORD` is no longer used.

Changelog Summary
- Add `Account::getPaymentOperations()` and unit tests
- Standardize amount formatting to 7 decimals; clarify PHPDocs
- Update PHPUnit 9 compatibility and fix PHP 8.3 deprecations
- Improve Horizon error handling for 404 JSON; throw on 4xx postTransaction
- Integration tests: auto-fund fixtures, skip without Horizon; use `STELLAR_NETWORK_PASSPHRASE`
- Normalize shell script line endings; docs on payments feed vs operations and amount precision

208 changes: 131 additions & 77 deletions Readme.md
Original file line number Diff line number Diff line change
@@ -1,96 +1,150 @@
## Description

PHP Library for interacting with the Stellar network.

* Communicate with Horizon server
* Build and sign transactions

## :warning: Danger Zone :warning:

**Development Status**

This library is under active development and should be considered beta quality.
Please ensure that you've tested extensively on a test network and have added
sanity checks in other places in your code.

:warning: [See the release notes for breaking changes](CHANGELOG.md)

**Large Integer Support**

The largest PHP integer is 64-bits when on a 64-bit platform. This is especially
important to pay attention to when working with large balance transfers. The native
representation of a single XLM (1 XLM) is 10000000 stroops.

Therefore, if you try to use a `MAX_INT` number of XLM (or a custom asset) it is
possible to overflow PHP's integer type when the value is converted to stroops and
sent to the network.

This library attempts to add checks for this scenario and also uses a `BigInteger`
class to work around this problem.

If your application uses large amounts of XLM or a custom asset please do extensive
testing with large values and use the `StellarAmount` helper class or the `BigInteger`
class if possible.

**Floating point issues**

Although not specific to Stellar or PHP, it's important to be aware of problems
when doing comparisons between floating point numbers.
## Description

PHP Library for interacting with the Stellar network.

* Communicate with Horizon server
* Build and sign transactions

## :warning: Danger Zone :warning:

**Development Status**

This library is under active development and should be considered beta quality.
Please ensure that you've tested extensively on a test network and have added
sanity checks in other places in your code.

:warning: [See the release notes for breaking changes](CHANGELOG.md)

**Large Integer Support**

The largest PHP integer is 64-bits when on a 64-bit platform. This is especially
important to pay attention to when working with large balance transfers. The native
representation of a single XLM (1 XLM) is 10000000 stroops.

Therefore, if you try to use a `MAX_INT` number of XLM (or a custom asset) it is
possible to overflow PHP's integer type when the value is converted to stroops and
sent to the network.

This library attempts to add checks for this scenario and also uses a `BigInteger`
class to work around this problem.

If your application uses large amounts of XLM or a custom asset please do extensive
testing with large values and use the `StellarAmount` helper class or the `BigInteger`
class if possible.

**Floating point issues**

Although not specific to Stellar or PHP, it's important to be aware of problems
when doing comparisons between floating point numbers.

For example:

```php
$oldBalance = 1.605;
$newBalance = 1.61;

var_dump($oldBalance + 0.005);
var_dump($newBalance);
if ($oldBalance + 0.005 === $newBalance) {
print "Equal\n";
}
else {
print "Not Equal\n";
}
```

The above code considers the two values not to be equal even though the same value
is printed out:

Output:
```
float(1.61)
float(1.61)
Not Equal
```

To work around this issue, always work with and store amounts as an integer representing stroops. Only convert
back to a decimal number when you need to display a balance to the user.

The static `StellarAmount::STROOP_SCALE` property can be used to help with this conversion.

## Installation

To install the latest release for usage in your project:

cd your_project/
composer require zulucrypto/stellar-api

If you want to work with the most recent development version you can use this repository:

git clone https://github.com/zulucrypto/stellar-api.git
cd stellar-api/
composer install

## Getting Started

See the [getting-started](getting-started/) directory for examples of how to use this library.

These examples are modeled after the ones in Stellar's getting started guide:

https://www.stellar.org/developers/guides/get-started/create-account.html

Additional examples are available in the [examples](examples/) directory

For example:
## Payments Feed vs. Payment Operations

```php
$oldBalance = 1.605;
$newBalance = 1.61;
Horizon’s `/accounts/{id}/payments` endpoint returns a mixed feed of records that are payment-related but include more than just payment operations. This library exposes two accessors on `Account`:

var_dump($oldBalance + 0.005);
var_dump($newBalance);
if ($oldBalance + 0.005 === $newBalance) {
print "Equal\n";
}
else {
print "Not Equal\n";
}
```
- `Account::getPayments($sinceCursor = null, $limit = 50)`
- Returns the heterogeneous feed as-is, mapping each record to a typed model.
- Includes: `create_account`, `payment`, `account_merge`, and `path_payment`.

The above code considers the two values not to be equal even though the same value
is printed out:
- `Account::getPaymentOperations($sinceCursor = null, $limit = 50)`
- Returns only payment-like operations.
- Includes: `payment`, `path_payment`.
- Excludes: `create_account`, `account_merge`.

Output:
```
float(1.61)
float(1.61)
Not Equal
```
Use `getPaymentOperations()` when you only care about actual transfer operations and want to ignore account creations or merges that may also appear in the payments feed.

To work around this issue, always work with and store amounts as an integer representing stroops. Only convert
back to a decimal number when you need to display a balance to the user.
When running integration tests, set the following environment variables:

The static `StellarAmount::STROOP_SCALE` property can be used to help with this conversion.
- `STELLAR_HORIZON_BASE_URL` (e.g., `http://localhost:8000/`)
- `STELLAR_NETWORK_PASSPHRASE` (e.g., `Integration Test Network ; zulucrypto`)

## Installation
Note: `STELLAR_NETWORK_PASSWORD` is no longer used.

To install the latest release for usage in your project:
Examples (choose one set):

cd your_project/
composer require zulucrypto/stellar-api
- Local integration network (Docker):
- `export STELLAR_HORIZON_BASE_URL=http://localhost:8000/`
- `export STELLAR_NETWORK_PASSPHRASE='Integration Test Network ; zulucrypto'`

If you want to work with the most recent development version you can use this repository:
- Stellar Testnet:
- `export STELLAR_HORIZON_BASE_URL=https://horizon-testnet.stellar.org/`
- `export STELLAR_NETWORK_PASSPHRASE='Test SDF Network ; September 2015'`

git clone https://github.com/zulucrypto/stellar-api.git
cd stellar-api/
composer install
- Stellar Public Network:
- `export STELLAR_HORIZON_BASE_URL=https://horizon.stellar.org/`
- `export STELLAR_NETWORK_PASSPHRASE='Public Global Stellar Network ; September 2015'`

## Getting Started
## Amount Formatting and Precision

See the [getting-started](getting-started/) directory for examples of how to use this library.
Stellar amounts are precise to 7 decimal places (1 XLM = 10,000,000 stroops). This library follows that convention:

These examples are modeled after the ones in Stellar's getting started guide:
- Display values (scaled):
- `StellarAmount::getScaledValue()` → returns a string with 7 decimal places (e.g., `"12.3400000"`).
- `AssetAmount::getBalance()` → same 7-decimal string.
- `Account::getNativeBalance()` → 7-decimal string; returns `"0.0000000"` when empty.

https://www.stellar.org/developers/guides/get-started/create-account.html
- Storage/comparison values (stroops):
- `StellarAmount::getUnscaledString()` → integer string of stroops (e.g., `"123400000"`).
- `AssetAmount::getUnscaledBalance()` → stroops as an integer string.
- `Account::getNativeBalanceStroops()` → stroops as an integer string.

Additional examples are available in the [examples](examples/) directory
Guidance:
- Do arithmetic and comparisons using stroops whenever possible.
- Format for display using the 7-decimal methods above.

## Donations

Stellar: GCUVDZRQ6CX347AMUUWZDYSNDFAWDN6FUYM5DVYYVO574NHTAUCQAK53
Stellar: GCUVDZRQ6CX347AMUUWZDYSNDFAWDN6FUYM5DVYYVO574NHTAUCQAK53
39 changes: 20 additions & 19 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,27 +1,28 @@
{
"name": "zulucrypto/stellar-api",
"description": "API client for the Stellar network",
"autoload": {
"psr-4": {
"ZuluCrypto\\StellarSdk\\": "src/",
"ZuluCrypto\\StellarSdk\\Test\\": "tests/"
}
},
{
"name": "zulucrypto/stellar-api",
"description": "API client for the Stellar network",
"autoload": {
"psr-4": {
"ZuluCrypto\\StellarSdk\\": "src/",
"ZuluCrypto\\StellarSdk\\Test\\": "tests/"
}
},
"require": {
"php": "^7.3 || ^8.0",
"guzzlehttp/guzzle": "^6.2",
"christian-riesen/base32": "^1.3",
"paragonie/sodium_compat": "^1.0",
"phpseclib/phpseclib": "^2.0.6",
"phpseclib/phpseclib": "^3.0",
"symfony/filesystem": "^4.1"
},
"license": "MIT",
"authors": [
{
"name": "Zulu Crypto",
"email": "zulucrypto@protonmail.com"
}
],
},
"license": "MIT",
"authors": [
{
"name": "Zulu Crypto",
"email": "zulucrypto@protonmail.com"
}
],
"require-dev": {
"phpunit/phpunit": "^6.4"
"phpunit/phpunit": "^9.6"
}
}
Loading