Seller onboarding
Bob precisa de um lugar para a Ishtaran mandar o dinheiro dele. A Mercatto poderia criar um para ele — mas em vez disso convida Bob a criar o dele próprio, para que a mesma identidade possa funcionar depois em outros marketplaces também, nunca presa dentro dos sistemas da própria Mercatto. Alice recebe o mesmo tratamento.
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
Três Accounts reais, cada uma autorizada para a Application da Mercatto — um passo fácil de
esquecer e que falha ruidosamente se pulado (veja Failure scenarios) — e
cada uma com uma ExecutionDestination registrada, sem a qual um Settlement real on-chain não
consegue pagá-las de jeito nenhum (veja Settlement and Split).
O que aconteceu por baixo dos panos
createAccountHolderInvitation não cria uma Account sozinha — a Account só existe depois que o
convite é resgatado. Existem dois métodos diferentes de resgate por um motivo:
signUpAndClaimInvitation é para quem nunca teve uma identidade na Ishtaran antes (Bob e Alice
aqui); um claimInvitation simples (sem cadastro) é para quem já tem uma sessão de
AccountHolder de um marketplace diferente, reutilizando a mesma Account subjacente — esse é o
verdadeiro motivo de dar a Bob o próprio login dele em primeiro lugar. A Mercatto nunca vê nenhuma
das duas senhas.
Alternativa coberta em outro lugar: um pagador avulso que nunca precisa do próprio login
recebe uma Account provisionada pela Organization no lugar (accounts.create, sem convite) — veja
Failure scenarios.
Um limite que vale conhecer agora, não depois: authorizeApplication exige a sessão de Member
da Mercatto (owner), não sua API Key — a chamada com API Key é rejeitada. O mesmo vale para tudo
sob workflows.* no próximo capítulo. Uma vez que Bob e Alice resgatam seus convites, porém, os
próprios logins deles deixam de ser úteis para o resto desta história — toda chamada financeira
posterior (saldo, saque) é a Mercatto agindo em nome deles com suas próprias credenciais, nunca a
sessão deles diretamente. Veja Known Limitations para entender exatamente
o porquê.
Registrar uma ExecutionDestination não é a mesma coisa que ter uma Account. Uma Account pode
ter saldo sem nunca ter um endereço real de recebimento on-chain registrado — é para isso que
existe a ExecutionDestination (DEC-037): o endereço para onde o execution leg de um Settlement
efetivamente paga, primeiro-a-registrar-vence, nunca sobrescrito silenciosamente. É
deliberadamente um mecanismo diferente da WithdrawalDestination (sem whitelist/cooldown) — isso
é um beneficiário declarando onde ele recebe como vendedor de um marketplace, não um saque
iniciado por um integrador. Antes deste capítulo rodar, a Mercatto também registra sua própria
execution wallet (examples/marketplace-mercatto/register-execution-wallet.ts) — uma wallet que a
Mercatto gera e assina inteiramente na própria máquina (só a chave pública estendida chega até a
Ishtaran); essa wallet é o que depois assina cada leg de Settlement em
Settlement and Split.