PHPackages                             weeasycrypto/weeasycrypto - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. weeasycrypto/weeasycrypto

ActiveLibrary

weeasycrypto/weeasycrypto
=========================

Official PHP SDK for the WeEasyCrypto tenant API — deposit addresses, balances, withdrawals, Ed25519 request signing and verified webhooks (no Composer dependencies; ext-sodium is bundled with PHP).

v0.2.0(1mo ago)00MITPHPPHP &gt;=8.1

Since Jul 17Pushed 1mo agoCompare

[ Source](https://github.com/weeasycrypto/php-sdk)[ Packagist](https://packagist.org/packages/weeasycrypto/weeasycrypto)[ Docs](https://github.com/weeasycrypto/sdk)[ RSS](/packages/weeasycrypto-weeasycrypto/feed)WikiDiscussions main Synced 1w ago

READMEChangelogDependencies (1)Versions (2)Used By (0)

weeasycrypto (PHP)
==================

[](#weeasycrypto-php)

Official PHP SDK for the WeEasyCrypto tenant API: deposit addresses, balances, deposits, withdrawals, and signed webhooks.

- **Zero Composer dependencies.** Only `php >= 8.1`, `ext-curl`, `ext-json`, `ext-sodium` (all bundled with PHP). A custom `HttpTransportInterface` is injectable for proxies or test stubs.
- **Signing you never hand-write.** Every request carries an Ed25519 signature (`X-Timestamp` + `X-Signature`, via `ext-sodium`) computed over the exact bytes sent on the wire — the platform holds only your public key and can verify, never forge. Webhook deliveries are Ed25519-signed too (`v1a`, per-tenant platform key) — verified with your tenant's public key, ±300 s tolerance.
- **Amounts are decimal strings**, never floats. `Amount::parse` / `Amount::format` use pure string arithmetic — no `floatval`, no bcmath.

> ⚠️ **Server-side only.** Your Ed25519 `privateKey` must never reach a browser or mobile bundle.

Install
-------

[](#install)

```
composer require weeasycrypto/weeasycrypto
```

Quickstart
----------

[](#quickstart)

```
use WeEasyCrypto\WeEasyCrypto;

$cv = new WeEasyCrypto([
    'baseUrl' => 'https://api.example.com',
    'apiKey' => getenv('WEEASYCRYPTO_API_KEY'),         // keyId, e.g. 'ck_…'
    'privateKey' => getenv('WEEASYCRYPTO_PRIVATE_KEY'), // hex Ed25519 seed, generated at issuance
    'webhookPublicKey' => getenv('WEEASYCRYPTO_WEBHOOK_PUBLIC_KEY'), // portal → Settings → Integrations
]);

// Issue a deposit address
$addr = $cv->addresses->create(['label' => 'user-42', 'chainKey' => 'tron']);
$addr['family']; // 'EVM' | 'TRON' | 'BTC' | 'SOL' | 'TON'

// Balances — amounts are decimal strings, never floats
$balances = $cv->balances->list();

// Deposits with auto-pagination
foreach ($cv->deposits->iterate(['status' => 'CONFIRMED']) as $deposit) {
    echo $deposit['txHash'], ' ', $deposit['amount'], PHP_EOL;
}
```

Resources return associative arrays in the wire shape (camelCase keys) — new server-side fields appear automatically and never break you.

Withdrawals — the idempotency contract
--------------------------------------

[](#withdrawals--the-idempotency-contract)

`requestId` is **your** idempotency key. Persist it in your own database *before* calling; the SDK deliberately never generates one, because a regenerated key after a crash is how double-payouts happen.

```
use WeEasyCrypto\Exception\ConflictException;

try {
    $w = $cv->withdrawals->create([
        'requestId' => 'wd-20260710-0001', // yours, persisted first
        'chainKey' => 'eth-mainnet',
        'tokenSymbol' => 'USDT',
        'to' => '0x…',
        'amount' => '100.5',               // always a string
    ]);
} catch (ConflictException $e) {
    if ($e->isDuplicateRequest()) {
        // Safety signal, not a failure: an earlier attempt already created it.
        // Look the withdrawal up via the id you stored against this requestId.
    } else {
        throw $e;
    }
}

// Poll to a terminal status (webhooks are the push-based alternative)
$final = $cv->withdrawals->waitUntilFinal($w['id']);
// $final['status']: 'CONFIRMED' | 'FAILED' | 'REJECTED' | 'CANCELED'
if ($final['status'] === 'CONFIRMED') {
    echo $final['txHash'];
}
```

Network errors on `withdrawals->create` / `createBatch` are retried automatically **with the same `requestId`** — that can never double-spend. `addresses->create` has no idempotency key, so it is never auto-retried; `list()` recent addresses before creating again if the outcome was unknown.

Webhooks
--------

[](#webhooks)

Deliveries carry `X-Webhook-Signature: t={ts},v1a={hex}` — an Ed25519 signature over `{ts}.{body}` made with a per-tenant platform key. Verification needs only your tenant's public key (`webhookSignPublicKey`in the merchant portal, Settings → Integrations); there is no shared secret to protect.

```
use WeEasyCrypto\Exception\WebhookVerificationException;

// Raw body must be the exact bytes received — do not re-serialize JSON.
$rawBody = file_get_contents('php://input');

try {
    $event = $cv->webhooks->parse($rawBody, $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'] ?? null);
} catch (WebhookVerificationException $e) {
    http_response_code(400);
    exit;
}

match ($event['type']) {
    'deposit.confirmed' => credit($event['data']['depositId'], $event['data']['amount']),
    'withdrawal.completed' => markPaid($event['data']['requestId']),
    default => null, // New event types appear over time — ignore what you don't know.
};
```

Errors
------

[](#errors)

```
WeEasyCryptoException
├─ ApiException (getStatus() / getErrorCode())
│   ├─ AuthenticationException(401)  ├─ PermissionException(403)
│   ├─ NotFoundException(404)        ├─ ConflictException(409)  // isDuplicateRequest()
│   ├─ ValidationException(422)      └─ ServerException(5xx)
│   └─ RateLimitException(429)       // getRetryAfterMs()
├─ NetworkException                   // no HTTP response; safe to replay withdrawals
├─ WebhookVerificationException
└─ TimeoutException                   // waitUntilFinal budget exceeded

```

Testing
-------

[](#testing)

```
composer install
vendor/bin/phpunit
```

Signing is verified against the shared golden vectors in [`../vectors/signing-vectors.json`](../vectors/signing-vectors.json).

###  Health Score

33

—

LowBetter than 72% of packages

Maintenance90

Actively maintained with recent releases

Popularity0

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity32

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

46d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/26592729?v=4)[Ailein](/maintainers/Ailein)[@Ailein](https://github.com/Ailein)

---

Top Contributors

[![Ailein](https://avatars.githubusercontent.com/u/26592729?v=4)](https://github.com/Ailein "Ailein (3 commits)")

---

Tags

cryptowebhookspaymentswithdrawalsweeasycryptodeposits

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/weeasycrypto-weeasycrypto/health.svg)

```
[![Health](https://phpackages.com/badges/weeasycrypto-weeasycrypto/health.svg)](https://phpackages.com/packages/weeasycrypto-weeasycrypto)
```

###  Alternatives

[cryptapi/php-cryptapi

CryptAPI's PHP library

2214.9k](/packages/cryptapi-php-cryptapi)[prevailexcel/laravel-nowpayments

A Laravel Package for NOWPayments

1422.7k](/packages/prevailexcel-laravel-nowpayments)[crypto-pay/binancepay

Binance Pay API for Laravel

213.7k](/packages/crypto-pay-binancepay)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
