تراکنشها و ایدمپوتنسی
هر جابهجایی موجودی در زربان سازمانی یک «تراکنش» است. سه نوع دارد:
| نوع | یعنی چه | دسترسی لازم |
|---|---|---|
TransactionTypeCoinDeposit | واریز روی زنجیره به آدرس حساب | CoinDepositScope |
TransactionTypeCoinWithdrawal | برداشت روی زنجیره به آدرس بیرونی | CoinWithdrawalScope |
TransactionTypeInternalTransfer | انتقال میان دو حساب همان سازمان | InternalTransferScope |
انتقال داخلی روی زنجیره نمیرود: کارمزد شبکه ندارد و آنی است.
فراخوانیهای این صفحه روی محیط عملیاتی اجرا میشوند و برداشت پس از خروج از صف قابل بازگشت نیست. گردش کار پیشنهادی برای اولین بار: simulate، سپس یک اجرای واقعی با کوچکترین مبلغ ممکن.
الگوی دو مرحلهای
هر تراکنش دو فراخوانی جدا دارد و این جداسازی عمدی است:
-
POST /transactions/simulate — همه اعتبارسنجیها را انجام میدهد و نتیجه را برمیگرداند، بدون آنکه چیزی جابهجا شود.
-
POST /transactions/submit — همان تراکنش را واقعاً اجرا میکند.
simulate سازوکار خشکاجرای این مسیر است: همان اعتبارسنجی و برآورد، بدون ثبت تراکنش. جای استفاده از آن هم توسعه است و هم تولید — پیش از نمایش تأییدیه به کاربر.
شبیهسازی
curl -sS -X POST "https://hd.zarban.io/transactions/simulate" \
-H "Authorization: Bearer $ZARBAN_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"accountId": 1234,
"type": "TransactionTypeCoinWithdrawal",
"input": {
"to": "0x1234567890abcdef1234567890abcdef12345678",
"amount": "25.5",
"symbol": "USDT",
"network": "arbitrum"
}
}'
اگر موجودی کافی نباشد، آدرس نامعتبر باشد یا مبلغ از حد مجاز شبکه کمتر باشد، همینجا خطا میگیرید — پیش از آنکه چیزی رخ داده باشد.
اجرا
curl -sS -X POST "https://hd.zarban.io/transactions/submit" \
-H "Authorization: Bearer $ZARBAN_TOKEN" \
-H "Content-Type: application/json" \
-H "x-transaction-uuid: 3f8a1c92-6b4d-4e77-9a03-1d2e5f7c8b90" \
-d '{
"accountId": 1234,
"type": "TransactionTypeCoinWithdrawal",
"input": {
"to": "0x1234567890abcdef1234567890abcdef12345678",
"amount": "25.5",
"symbol": "USDT",
"network": "arbitrum"
}
}'
تفاوت با شبیهسازی فقط یک چیز است: هدر x-transaction-uuid.
x-transaction-uuid — قاعدهای که نباید بشکنید
این هدر روی submit الزامی است و رفتارش دقیقاً این است:
- ارسال دوباره با همان UUID و همان پارامترها، تراکنش اصلی را برمیگرداند و تراکنش دومی نمیسازد.
- استفاده دوباره از همان UUID با پارامترهای متفاوت، با
409رد میشود.
قاعده: UUID را پیش از اولین تلاش بسازید، آن را کنار رکورد قصد پرداخت در پایگاه داده خودتان ذخیره کنید، و در هر تلاش مجدد همان را بفرستید.
سرور از روی همین مقدار تشخیص میدهد که درخواست تکراری است. اگر UUID را داخل خودِ تابع تلاش مجدد بسازید، هر تلاش مقدار تازهای میگیرد و سرور آن را تراکنشی جدید میشمارد. خطر این کار آنجا روشن میشود که شبکه پس از ارسال درخواست و پیش از رسیدن پاسخ قطع شود؛ آن وقت تلاش مجدد، برداشت دومی ثبت میکند.
الگوی درست:
-
رکورد «قصد برداشت» را در پایگاه داده خود بسازید، با یک UUID تازه در ستونی کنارش.
-
submitرا با همان UUID صدا بزنید. -
اگر پاسخ نرسید یا خطای شبکه گرفتید، همان درخواست را با همان UUID دوباره بفرستید. اگر تراکنش قبلاً ساخته شده باشد، همان را پس میگیرید.
-
اگر
409گرفتید، یعنی همان UUID را با پارامتری متفاوت فرستادهاید. این باگ سمت شماست؛ دوباره تلاش نکنید و هشدار بدهید.
وضعیت تراکنش
curl -sS "https://hd.zarban.io/transactions/55012" \
-H "Authorization: Bearer $ZARBAN_TOKEN"
| وضعیت | یعنی چه |
|---|---|
TransactionStatusPending | ثبت شده، هنوز شروع نشده |
TransactionStatusInProgress | در حال اجرا |
TransactionStatusPendingManualApproval | منتظر تأیید دستی است |
TransactionStatusSuccess | انجام شد |
TransactionStatusFailed | ناموفق |
TransactionStatusRejectedByAdmin | رد شد |
TransactionStatusCancelledByUser | لغو شد |
TransactionStatusSuccess تنها وضعیت پایانیِ موفق است. Pending و InProgress و PendingManualApproval هنوز تمام نشدهاند — موجودی را بر اساس آنها به کاربر نشان ندهید و کالا یا خدمتی تحویل ندهید.
برای دنبال کردن وضعیت، بهجای فراخوانی مکرر API، وبهوک بگیرید.
فهرست تراکنشها
curl -sS "https://hd.zarban.io/transactions?accountId=1234" \
-H "Authorization: Bearer $ZARBAN_TOKEN"
بدون accountId، همه تراکنشهای سازمان برمیگردد. با فیلترهای type و status هم میتوانید محدودش کنید.
همین فهرست، با همین فیلترها، در داشبورد سازمانی هم هست — جای مناسبی برای بررسی یک تراکنش مشکوک بدون نوشتن کد:

لغو برداشت
curl -sS -X POST "https://hd.zarban.io/transactions/55012/cancel" \
-H "Authorization: Bearer $ZARBAN_TOKEN"
لغو تنها تا وقتی ممکن است که برداشت هنوز در وضعیت ثبتشده در صف باشد و روی زنجیره ارسال نشده باشد. پس از ارسال، دیگر راه بازگشتی نیست.
اگر رابط کاربری شما دکمه «لغو» دارد، وضعیت را پیش از نمایش دکمه بخوانید و پ اسخ فراخوانی لغو را هم بررسی کنید: تراکنش ممکن است در همان فاصله از صف خارج و ارسال شده باشد.
لغو موفق، موجودی رزروشده را آزاد میکند و درخواست را از صف برداشت بیرون میبرد.
صف برداشت
curl -sS "https://hd.zarban.io/tenants/PLN/withdraw-queue" \
-H "Authorization: Bearer $ZARBAN_TOKEN"
برداشتهایی که ثبت شدهاند اما هنوز روی زنجیره نرفتهاند. برای نظارت عملیاتی به کار میآید: صفی که طولانی میشود، معمولاً یعنی موجودی کیف پول داغ سازمان رو به اتمام است.
انتقال داخلی
curl -sS -X POST "https://hd.zarban.io/transactions/submit" \
-H "Authorization: Bearer $ZARBAN_TOKEN" \
-H "Content-Type: application/json" \
-H "x-transaction-uuid: 7c1e4a05-9f3b-4d28-8e61-0a5b6c7d8e9f" \
-d '{
"accountId": 1234,
"type": "TransactionTypeInternalTransfer",
"input": {
"debitAccountId": 1234,
"creditAccountId": 5678,
"symbol": "USDT",
"amount": "10",
"memo": "invoice #42"
}
}'
هر دو حساب باید به سازمان شما تعلق داشته باشند. همان قاعده x-transaction-uuid اینجا هم برقرار است.