Seller onboarding
Bob necesita un lugar al que Ishtaran pueda enviar su dinero. Mercatto podría crear uno por él — pero en cambio lo invita a crear el suyo propio, para que la misma identidad pueda funcionar después con otros marketplaces también, nunca atrapada dentro de los sistemas de Mercatto. Alice recibe el mismo tratamiento.
Código
const bobInvitation = await mercatto.accounts.createAccountHolderInvitation(organizationId, `bob-${runId}`);
const bob = createClient();
const bobClaim = await bob.accountHolders.signUpAndClaimInvitation(bobInvitation.plainTextToken, emails.bob, STORY_PASSWORD);
const bobAccountId = (await bob.accountHolders.me()).accountId;
// Alice, the buyer, gets the identical treatment — not an "anonymous" payer.
const aliceInvitation = await mercatto.accounts.createAccountHolderInvitation(organizationId, `alice-${runId}`);
// … same claim flow …
// Mercatto's own commission lands in an Account it owns directly — no invitation needed.
const mercattoRevenueAccountId = (await mercatto.accounts.create(organizationId, `mercatto-revenue-${runId}`)).accountId;
await owner.accounts.authorizeApplication(organizationId, bobAccountId, applicationId);
await owner.accounts.authorizeApplication(organizationId, aliceAccountId, applicationId);
await owner.accounts.authorizeApplication(organizationId, mercattoRevenueAccountId, applicationId);
// DEC-037 — where does Ishtaran actually send Bob's money? Bob's own wallet, entirely outside
// Ishtaran (Mercatto never touches his private key). Mercatto's own commission, by contrast, lands
// on an address of Mercatto's OWN execution wallet — registered just before this chapter runs
// (`register-execution-wallet.ts`), the same wallet that later signs every Settlement leg.
const bobsOwnWallet = wallet.generate();
const bobDestinationAddress = deriveTronAddress(bobsOwnWallet.wallet.accountExtendedPublicKey, 0);
await mercatto.executionDestinations.register(organizationId, bobAccountId, assetNetworkId, bobDestinationAddress);
const mercattoRevenueAllocation = await mercatto.wallets.allocateDepositAddress(applicationId, networkId);
await mercatto.executionDestinations.register(organizationId, mercattoRevenueAccountId, assetNetworkId, mercattoRevenueAllocation.address);
Resultado
Tres Accounts reales, cada una autorizada para la Application de Mercatto — un paso fácil de
olvidar y que falla de forma ruidosa si se omite (ver Failure scenarios) —
y cada una con un ExecutionDestination registrado, sin el cual un Settlement real on-chain no
puede pagarles en absoluto (ver Settlement and Split).
Qué pasó por debajo
createAccountHolderInvitation no crea una Account por sí sola — la Account solo existe una vez
que la invitación es reclamada. Existen dos métodos de reclamo distintos por una razón:
signUpAndClaimInvitation es para alguien que nunca tuvo una identidad en Ishtaran (Bob y Alice
aquí); un simple claimInvitation (sin registro) es para alguien que ya tiene una sesión de
AccountHolder de un marketplace distinto, reutilizando la misma Account subyacente — ese es el
verdadero propósito de darle a Bob su propio login desde el principio. Mercatto nunca ve ninguna
de las dos contraseñas.
Alternativa cubierta por separado: un pagador ocasional que nunca necesita su propio login
recibe en cambio una Account provisionada por la Organization (accounts.create, sin invitación)
— ver Failure scenarios.
Un límite que conviene conocer ahora, no después: authorizeApplication requiere la sesión de
Member de Mercatto (owner), no su API Key — la llamada con API Key es rechazada. Lo mismo aplica
a todo lo que esté bajo workflows.* en el próximo capítulo. Sin embargo, una vez que Bob y Alice
reclamaron sus invitaciones, sus propios logins dejan de ser útiles para el resto de esta historia
— cada llamada financiera posterior (balance, retiro) la hace Mercatto en su nombre con sus
propias credenciales, nunca con la sesión de ellos directamente. Ver
Known Limitations para entender exactamente por qué.
Registrar un ExecutionDestination no es lo mismo que tener una Account. Una Account puede
tener balance sin tener nunca en registro una dirección real de recepción on-chain — para eso
existe ExecutionDestination (DEC-037): la dirección a la que realmente paga la execution leg
de un Settlement, primer registro gana, nunca se sobrescribe en silencio. Deliberadamente no es el
mismo mecanismo que WithdrawalDestination (sin whitelist ni cooldown) — esto es un beneficiario
declarando dónde le pagan como vendedor de un marketplace, no un retiro iniciado por el
integrador. Antes de que corra este capítulo, Mercatto también registra su propia execution
wallet (examples/marketplace-mercatto/register-execution-wallet.ts) — una wallet que Mercatto
genera y con la que firma enteramente en su propia máquina (solo la extended public key llega
alguna vez a Ishtaran); esa wallet es la que más adelante firma cada leg de Settlement en
Settlement and Split.