Charge
Take credits right away, or hold them first for long jobs.
Charge
await credits.charge({ user, credits: 5 });Or charge an action from your price list, which you set in the dashboard:
await credits.charge({ user, action: "chat.message" });
await credits.charge({ user, action: "video.render", quantity: 12 }); // 12 secondsThe charge settles on NEAR before the call returns.
Hold, then charge
For long or uncertain work, hold the most it could cost. Then capture what it actually cost, or release it if the work fails.
const hold = await credits.hold({ user, credits: 100 });
try {
const cost = await render(job);
await credits.capture(hold.holdId, { credits: cost }); // the rest goes back
} catch {
await credits.release(hold.holdId); // the user keeps everything
}Holds release on their own after an hour.
Refund
await credits.refund({ user, credits: 5 });You can refund up to what the user spent with your app. You can also refund any charge from the dashboard.
Who signs a charge
Every live charge, hold, capture and refund is a NEAR transaction from your app's own account, such as app-39cbd0db321ad08a.apps.kredo-network.testnet. The vault accepts them from no one else, including Kredo's servers.
- That account has a single function-call key. It can call
charge,hold,capture,releaseandrefundon the vault, and nothing else. It can't move USDT or NEAR, or add keys. - If the key leaks, it can only charge your app's users, within the limits they approved, into your own earnings.
- Your payout account can move your app to a new signer at any time by calling
set_app_signeron the vault. Kredo can't. - You never pay gas. The SDK signs a meta transaction (NEP-366), and the network sends it and pays.
On testnet, Kredo creates your signer account and gives you its key once. The dashboard doesn't do this yet. Since that key passed through Kredo, rotate it if you want a key only you have ever held: make your own account with a function-call key for those five methods, then point your app at it with set_app_signer.
No double charges
Pass your own ref, such as a message or order id. The same ref always returns the first result, so a retry can never charge twice.
await credits.charge({ user, credits: 5, ref: orderId });