پرش به مطلب اصلی

واریز و برداشت رمزارز

برای توسعه‌دهندگان: این محصول از طریق API زربان سازمانی در دسترس است و به دو دسترسی «واریز کوین» (CoinDepositScope) و «برداشت کوین» (CoinWithdrawalScope) نیاز دارد. نگاه کنید به تراکنش‌ها و ایدمپوتنسی و وب‌هوک‌ها.

واریز و برداشت رمزارز، پایه‌ای‌ترین سرویس زربان سازمانی است. هر حساب روی شبکه‌های پشتیبانی‌شده آدرس واریز اختصاصی خود را می‌گیرد، با آن رمزارز تحویل می‌گیرد و موجودی‌اش را به نشانی‌های بیرون از زربان می‌فرستد. سه سرویس دیگر — سپرده‌گذاری، وام و گواهی وثیقه — همگی روی موجودی‌ای کار می‌کنند که از همین راه به حساب رسیده است.

کلید خصوصی از زیرساخت زربان بیرون نمی‌آید و در پاسخ هیچ فراخوانی هم نمی‌آید. سرویس شما تنها اعلام می‌کند که چه تراکنشی باید انجام شود؛ امضای آن کار زربان است.

درخواست دمو

شبکه‌های پشتیبانی‌شده

این سرویس اکنون روی پنج شبکه کار می‌کند:

شبکهدارایی بومیاستاندارد توکننیاز به شناسه پرداخت
آربیترومETHERC-20خیر
اتریومETHERC-20خیر
زنجیره هوشمند بی‌ان‌بیBNBBEP-20خیر
ترونTRXTRC-20خیر
تونTONجتونبله

شبکه‌های تازه به درخواست سازمان اضافه می‌شوند. اگر کاربران شما شبکه‌ای می‌خواهند که در این فهرست نیست، همان ابتدا و در مرحله طراحی مطرحش کنید.

آنچه در این جدول آمده وضعیت کلی سرویس است، نه آنچه همین حالا برای سازمان شما فعال است. مرجع اصلی، دو فراخوانی‌اند: GET /networks شبکه‌های فعال را فهرست می‌کند و GET /coins پیکربندی واریز و برداشت هر رمزارز را به تفکیک شبکه می‌دهد. فهرست شبکه‌ها و رمزارزها را در رابط کاربری از پاسخ همین دو بسازید؛ اگر این مقادیر را در کد ثابت بنویسید، با نخستین تغییر پیکربندی، کارتان از واقعیت عقب می‌افتد.

دارایی بومی و توکن

سرویس هر دو دسته دارایی را پشتیبانی می‌کند و پاسخ GET /coins تفاوتشان را صریح نشان می‌دهد:

  • دارایی بومی شبکه، مانند ETH روی اتریوم یا TRX روی ترون. در پیکربندی واریز، isNativeAsset برابر true می‌آید و coinAddress خالی می‌ماند.
  • توکن قراردادی، مانند USDT روی ترون یا USDC روی آربیتروم. اینجا isNativeAsset برابر false است و coinAddress نشانی قرارداد توکن را روی همان شبکه می‌دهد.

یک رمزارز ممکن است روی چند شبکه در دسترس باشد و هر ترکیب رمزارز و شبکه، وضعیت مستقل خودش را دارد. isOperational در پیکربندی واریز و برداشت جداگانه می‌آید؛ پس ممکن است واریز یک توکن روی شبکه‌ای باز باشد، اما برداشت همان توکن روی همان شبکه فعلاً بسته بماند.

واریز

برای گرفتن آدرس واریز، GET /accounts/{id}/coindepositaddress را با symbol و network صدا بزنید. اگر برای آن ترکیبِ حساب و رمزارز و شبکه هنوز آدرسی ساخته نشده باشد، زربان در همان فراخوانی نخست آن را می‌سازد.

پاسخ، جز خود آدرس، این فیلدها را هم دارد:

  • memo — شناسه پرداختی که بعضی شبکه‌ها برای نسبت‌دادن واریز به آدرس لازم دارند. روی شبکه تون این مقدار پر می‌آید و باید آن را کنار آدرس به کاربر نشان دهید؛ واریزی که این شناسه را نداشته باشد، به هیچ حسابی نمی‌نشیند. روی شبکه‌هایی که چنین شناسه‌ای نمی‌خواهند، خالی برمی‌گردد.
  • isActive — نشان می‌دهد که واریز به این آدرس همچنان به حساب می‌نشیند یا نه.
  • isDeprecated — نشان می‌دهد که نسخه تازه‌تری جای این آدرس را گرفته است. آدرس منسوخ را دیگر به کاربر نشان ندهید، ولی از سوابق هم پاکش نکنید؛ واریزهای قدیمی هنوز به همین آدرس ارجاع می‌دهند.

وقتی تراکنش روی زنجیره نشست و تأیید شد، زربان تراکنشی از نوع TransactionTypeCoinDeposit روی حساب ثبت می‌کند. در نتیجه آن، مبلغ ناخالصی که روی زنجیره دیده شده (amount)، مبلغی که پس از کسورات به حساب نشسته (creditedAmount)، نشانی فرستنده، درهم‌سازی تراکنش و زمان ثبت را می‌بینید.

برای هر حساب و هر شبکه، آدرس واریز را جداگانه بگیرید. اگر یک آدرس را میان چند کاربر مشترک کنید، دیگر نمی‌توان تشخیص داد هر واریز به کدام حساب تعلق دارد.

برداشت

برداشت در دو مرحله انجام می‌شود. شرح کامل این الگو در تراکنش‌ها و ایدمپوتنسی آمده است:

  1. شبیه‌سازی با POST /transactions/simulate. زربان تراکنش را اعتبارسنجی می‌کند و کارمزد و مانده پس از برداشت را بدون اجرا حساب می‌کند. همین نتیجه است که باید پیش از تأیید نهایی جلوی چشم کاربر بگذارید.
  2. اجرا با POST /transactions/submit و نوع TransactionTypeCoinWithdrawal. در ورودی، نشانی مقصد، مبلغ، رمزارز، شبکه و در صورت نیاز شناسه پرداخت را می‌فرستید.

در مرحله اجرا، هدر x-transaction-uuid اجباری است و نقش کلید ایدمپوتنسی1 را دارد: اگر همان مقدار را دوباره بفرستید، زربان درخواست را از نو اجرا نمی‌کند و پاسخ همان تراکنش نخست را برمی‌گرداند. اهمیت این کلید آنجا روشن می‌شود که پاسخ در میانه راه قطع شود؛ در چنین حالتی، همین کلید جلوی برداشت دوباره از حساب کاربر را می‌گیرد.

پیکربندی برداشت هر رمزارز، دو محدودیت را هم اعلام می‌کند: minWithdraw کمترین مبلغی است که روی آن شبکه می‌توان برداشت کرد و withdrawTax کارمزدی که به‌صورت کسری اعشاری از مبلغ کم می‌شود. در نتیجه برداشت، مبلغی که واقعاً ارسال شده، کارمزد کسرشده، درهم‌سازی تراکنش، نشانی آن در کاوشگر بلاک و مانده پس از برداشت می‌آید.

لغو و صف برداشت

تا وقتی درخواست برداشت ثبت شده اما هنوز روی زنجیره نرفته است، می‌توانید آن را با POST /transactions/{id}/cancel لغو کنید. با لغو، موجودی رزروشده به حساب برمی‌گردد و درخواست از صف بیرون می‌رود. اما همین که تراکنش ارسال شد، دیگر راهی برای لغو نمی‌ماند.

GET /tenants/{id}/withdraw-queue برداشت‌های تسویه‌نشده سازمان را برمی‌گرداند: هم آن‌هایی که در صف پرداخت مانده‌اند و هم آن‌هایی که ارسال شده‌اند و منتظر تأیید روی زنجیره‌اند. کنار این فهرست، totals تقاضای در صف را به تفکیک رمزارز و شبکه جمع می‌زند تا بدانید هر کیف پول گرم را چقدر باید شارژ کنید. در این جمع، تنها برداشت‌های هنوز ارسال‌نشده به حساب می‌آیند.

معماری نگهداری کلید

نگهداری کلید و امضای تراکنش، میان سه جزء تقسیم شده است:

  • کیف پول سلسله‌مراتبی قطعی2 — آدرس واریز هر حساب روی هر شبکه، از شاخه‌ای مستقل از کلید اصلی سازمان مشتق می‌شود. به این ترتیب آدرس هر حساب یکتا می‌ماند، بی‌آنکه لازم باشد برای هر حساب کلید جداگانه‌ای ساخته و نگهداری شود.
  • کیف پول گرم3 — زربان برداشت‌ها را از کیف پول گرمِ هر شبکه پرداخت می‌کند، نه مستقیم از آدرس واریز کاربران. موجودی این کیف پول‌ها را با GET /tenants/{id}/hot-wallet-balances می‌بینید و اگر موجودی پایین بیاید، سامانه هشدار عملیاتی می‌دهد.
  • سرویس امضای تراکنش — کلید خصوصی تنها در این سرویس در دسترس است و امضا هم همان‌جا انجام می‌شود. هیچ مسیری در API کلید را برنمی‌گرداند و کلید هیچ‌گاه به دست سرویس شما نمی‌رسد.

حاصل این تقسیم‌بندی آن است که مسیر زربان سازمانی امانی4 می‌شود. تفاوت این مسیر با پروتکل غیرامانی را در صفحه زربان سازمانی توضیح داده‌ایم.

وب‌هوک‌ها

برای باخبر شدن از واریزها لازم نیست API را مدام صدا بزنید. سازمان با POST /webhooks/{entityId} یک نشانی امن ثبت می‌کند و زربان رویدادها را به همان نشانی می‌فرستد.

دو رویداد به این سرویس مربوط می‌شوند:

رویدادمعنا
WebhookTransactionCoinDepositواریزی روی زنجیره تأیید شد و به حساب نشست.
WebhookTransactionCoinWithdrawalبرداشتی روی زنجیره ارسال شد.

پیامی که تحویل داده می‌شود، پوششی ثابت دارد: type دسته رویداد را می‌گوید، name نام دقیق آن را، و payload بدنه رویداد را، که در این دو مورد خودِ تراکنش است.

هر وب‌هوک کلید امضای خودش را دارد. زربان این کلید را تنها هنگام ساختن وب‌هوک یا چرخاندن کلید به‌صورت کامل برمی‌گرداند؛ در فهرست و مشاهده، فقط شکل پوشیده آن را می‌بینید. کلید را با PUT /webhooks/{entityId}/signing-key بچرخانید. پیش از پردازش هر پیام، امضای آن را بررسی کنید؛ روش کار و نمونه کد در وب‌هوک‌ها آمده است.

سوابق تحویل را با GET /webhooks/{entityId}/logs بخوانید؛ برای هر تلاش، بدنه ارسالی، پاسخ دریافتی، کد وضعیت، زمان رفت‌وبرگشت و تعداد تلاش‌های دوباره در آن ثبت شده است. اگر رویدادی گم شد، پیش از هر چیز سراغ همین فهرست بروید.

وضعیت تراکنش

هر تراکنش واریز یا برداشت، یکی از این وضعیت‌ها را دارد:

وضعیتمعنا
TransactionStatusPendingثبت شده و در انتظار پردازش است.
TransactionStatusInProgressدر حال اجراست.
TransactionStatusPendingManualApprovalدر انتظار تأیید دستی است.
TransactionStatusSuccessبا موفقیت انجام شد.
TransactionStatusFailedناموفق بود.
TransactionStatusRejectedByAdminمدیر آن را رد کرد.
TransactionStatusCancelledByUserپیش از ارسال لغو شد.

از میان این وضعیت‌ها، تنها TransactionStatusSuccess و TransactionStatusFailed نهایی‌اند. بقیه را در سامانه خود قطعی نگیرید و موجودی کاربر را بر پایه آن‌ها آزاد نکنید.

مطالب مرتبط

Footnotes

  1. Idempotency

  2. Hierarchical Deterministic Wallet — HD Wallet

  3. Hot wallet

  4. Custodial