06 · Configuración de entornos y aceptación
Parámetros de red, activo de demostración, ejemplos de consulta y lista de aceptación para los entornos públicos.
6.1 Entornos
| Elemento | Pruebas | Demostración mainnet |
|---|---|---|
| Uso | Desarrollo, integración, aceptación | Verificación de capacidades |
| Red | Bohr Testnet | BOT Mainnet |
| Estado | Disponible | Suite desplegada |
| Chain ID | 968 | 677 |
| RPC | https://rpc.bohr.life | https://rpc.botchain.ai |
| Explorador | https://scan.bohr.life | https://scan.botchain.ai |
| Gas | BOT de prueba | BOT |
Direcciones, saldos, identidades y Claims son independientes.
6.2 Estructura recomendada
type RwaEnvironment = {
chainId: number;
rpcUrl: string;
explorerUrl: string;
contracts: {
token: string;
identityRegistry: string;
onchainIdGateway?: string;
idFactory?: string;
claimIssuer?: string;
};
};
const rwaTestnet = {
chainId: 968,
rpcUrl: 'https://rpc.bohr.life',
explorerUrl: 'https://scan.bohr.life',
contracts: {
token: '0x922835859623d6F3b99a2742D585E093bBA0a740',
identityRegistry: '0x17e33C394Ab783D6786011d01681D8Ad540C5F53',
onchainIdGateway: '0x3B0FE2CD501534cbcbD1F97ec823Da535fc0224f',
idFactory: '0xb4E03AB303f4c42dbced87b65e1d9f5788EAb369',
claimIssuer: '0x67EC753196D6Cd1B65a29b6ff9c1bE41E554a5a7',
},
};
const rwaMainnet = {
chainId: 677,
rpcUrl: 'https://rpc.botchain.ai',
explorerUrl: 'https://scan.botchain.ai',
contracts: {
token: '0x9115A020821fDFdf265Eea8788a500d17557c370',
identityRegistry: '0x7752dd107CDec2dF5feD585BCC70457c5312021a',
onchainIdGateway: '0xa6B4E53128915E0f980DD455De9F70B6Dc61E1ee',
idFactory: '0x124ED389600870D1a5f86f657896Add3E623ca9e',
claimIssuer: '0x3950eB42733b3eF6744E8788C741788CCF6c84b3',
},
};
No retroceda automáticamente a testnet si mainnet falta o falla. JSON mainnet.
6.3 Activo público
| Elemento | Valor |
|---|---|
| Nombre / símbolo / decimales | Project Real World Asset / PRWA / 6 |
| Topic | KYC_APPROVED |
| Valor Topic | 7151541257903274562366177585585886223835338030660388602590463654390840817671 |
| Scheme | 1 |
| Países | 156, 702 |
6.3.1 Bohr Testnet
| Contrato | Dirección |
|---|---|
Token | 0x922835859623d6F3b99a2742D585E093bBA0a740 |
IdentityRegistry | 0x17e33C394Ab783D6786011d01681D8Ad540C5F53 |
IdentityRegistryStorage | 0xB834C4FEEADC24A9c5B873e8887CD9b54C40E98D |
ClaimTopicsRegistry | 0xbf8adD07A8722d06c218A3A7DD4Bb44d3a90948A |
TrustedIssuersRegistry | 0x94ffe710F64AB382274A53C8b10003a3287E621D |
ModularCompliance | 0x1E2e2a848b611C121C86F77C703B8DD32DCdE37A |
| Token ONCHAINID | 0x551676B9061b5324676BBbB5587433454EE54521 |
| Compartido | Dirección |
|---|---|
ONCHAINID Gateway | 0x3B0FE2CD501534cbcbD1F97ec823Da535fc0224f |
IdFactory | 0xb4E03AB303f4c42dbced87b65e1d9f5788EAb369 |
ClaimIssuer | 0x67EC753196D6Cd1B65a29b6ff9c1bE41E554a5a7 |
TREXGateway | 0x82e1Fa8022BA1dcFC05061E0A1CE828C189108A9 |
| Country Allowlist | 0x532bFc29B0D9a281084203303a8E687259D57149 |
6.3.2 BOT Mainnet
| Contrato | Dirección |
|---|---|
Token | 0x9115A020821fDFdf265Eea8788a500d17557c370 |
IdentityRegistry | 0x7752dd107CDec2dF5feD585BCC70457c5312021a |
IdentityRegistryStorage | 0xD54fD1381c970F19366cb7c50072295045ff5516 |
ClaimTopicsRegistry | 0x645E33c8c67D3Ea478F87b70d76711E110953FB9 |
TrustedIssuersRegistry | 0x4d96f4Bb96795a3EFeb3Cea43459E2ee4C5ad439 |
ModularCompliance | 0xB8A4b2aFd8318e61cDbaEC07559B49bE6bBE20D5 |
| Token ONCHAINID | 0x3677B0F87892B10F1341DB3348dFEcb9CE039146 |
| Compartido | Dirección |
|---|---|
ONCHAINID Gateway | 0xa6B4E53128915E0f980DD455De9F70B6Dc61E1ee |
IdFactory | 0x124ED389600870D1a5f86f657896Add3E623ca9e |
ClaimIssuer | 0x3950eB42733b3eF6744E8788C741788CCF6c84b3 |
TREX ImplementationAuthority | 0x3E19c7f1e6E53125fF205591fc516e25541d21ff |
ONCHAINID ImplementationAuthority | 0x992CCAC1A33EFdb58b9cfD49CF510d5db15Fc249 |
IAFactory | 0xf3BdD013eb6c49C23f5b8E70bE5F6C8c98c76028 |
TREXFactory | 0xf622AbFDf470912CCb86A54d52D2430951a3e956 |
TREXGateway | 0x3c209A13fc9E91B060C7672874895E117a1A3Ab5 |
| Country Allowlist | 0xA41A626bcBF57B3695539f6516E3D482dCFAEDEC |
Country Allowlist no ha completado una auditoría de producción. La Suite es solo de demostración técnica y no debe portar activos reales.
6.4 Carteras públicas
| Ejemplo | Cartera | ONCHAINID testnet | País | Verificado |
|---|---|---|---|---|
| Alice | 0xb450970Eece71044acF7cB7f53Ee51e3BC2EA922 | 0xfAB41B1DfD098F439D75cEA0cb48f70B46052544 | 156 | true |
| Bob | 0xfc996C5378fe0cd03Fd4296075abc07B16b2B12F | 0xd3b816e7494e918297E3553d65488a7E0682C6A3 | 702 | true |
| Cathy | 0x2b981b025397AE1AFca6f8DC7A2f5C7A868dEe78 | 0xb7522A6649a20A0820E292D8D0f35aB792812011 | 156 | true |
No se proporcionan claves privadas. Para escritura, use una cartera propia.
| Ejemplo | Cartera | ONCHAINID mainnet | País | Verificado |
|---|---|---|---|---|
| Alice | 0xb450970Eece71044acF7cB7f53Ee51e3BC2EA922 | 0x95d0ae16d03A26BA6a0dA844938C5c50e16e407C | 156 | true |
| Bob | 0xfc996C5378fe0cd03Fd4296075abc07B16b2B12F | 0x3F5059a5eadc24c27809f481e97Bef4834DB4272 | 702 | true |
| Cathy | 0x2b981b025397AE1AFca6f8DC7A2f5C7A868dEe78 | 0x29E0cb659BEd6baF5a6Dc19C50cB41dbBdd41194 | 156 | true |
Para negativos, use una cartera propia no registrada: contains == false, isVerified == false.
6.5 Validar red y contrato
Ejemplos con ethers.js v5:
const { ethers } = require('ethers');
const provider = new ethers.providers.JsonRpcProvider('https://rpc.bohr.life');
const network = await provider.getNetwork();
if (network.chainId !== 968) {
throw new Error(`Wrong network: expected 968, got ${network.chainId}`);
}
const TOKEN = '0x922835859623d6F3b99a2742D585E093bBA0a740';
const IR = '0x17e33C394Ab783D6786011d01681D8Ad540C5F53';
if (await provider.getCode(TOKEN) === '0x') {
throw new Error('Token contract not found on current network');
}
Valide Chain ID antes de escribir.
6.6 Leer el activo
const token = new ethers.Contract(TOKEN, [
'function name() view returns (string)',
'function symbol() view returns (string)',
'function decimals() view returns (uint8)',
'function totalSupply() view returns (uint256)',
'function identityRegistry() view returns (address)',
'function compliance() view returns (address)',
'function paused() view returns (bool)',
], provider);
const [name, symbol, decimals, supply, registry, compliance, paused] =
await Promise.all([
token.name(), token.symbol(), token.decimals(), token.totalSupply(),
token.identityRegistry(), token.compliance(), token.paused(),
]);
console.log({name, symbol, decimals,
totalSupply: ethers.utils.formatUnits(supply, decimals),
registry, compliance, paused});
Acepte cuando nombre/símbolo, decimals, IR y MC coincidan con la publicación.
6.7 Saldo y elegibilidad
const wallet = '0xb450970Eece71044acF7cB7f53Ee51e3BC2EA922';
const ir = new ethers.Contract(IR, [
'function contains(address) view returns (bool)',
'function isVerified(address) view returns (bool)',
'function identity(address) view returns (address)',
'function investorCountry(address) view returns (uint16)',
], provider);
const [rawBalance, contains, verified, identity, country] =
await Promise.all([
token.balanceOf(wallet), ir.contains(wallet), ir.isVerified(wallet),
ir.identity(wallet), ir.investorCountry(wallet),
]);
console.log({balance: ethers.utils.formatUnits(rawBalance, decimals),
contains, verified, identity, country});
Las muestras deben devolver contains y verified verdaderos.
6.8 Eventos
const latest = await provider.getBlockNumber();
const logs = await token.queryFilter(
token.filters.Transfer(), Math.max(0, latest - 5000), latest
);
for (const log of logs) {
console.log({
txHash: log.transactionHash, blockNumber: log.blockNumber,
from: log.args.from, to: log.args.to,
value: ethers.utils.formatUnits(log.args.value, decimals),
});
}
Consulte por tramos y checkpoints.
6.9 Escrituras
| Operación | Firmante | Requisito |
|---|---|---|
| Crear ONCHAINID | Cartera inversor | Gas |
addClaim | Gestor ONCHAINID | Firma Claim |
registerIdentity | IR Agent | Soporte del emisor |
mint / burn | Token Agent | Soporte del emisor |
transfer | Titular | Elegibilidad y reglas |
Nunca transfiera claves privadas. Los PRWA públicos están pausados; transfer solo funciona después de unpause().
const recipient = '0xfc996C5378fe0cd03Fd4296075abc07B16b2B12F';
const senderAddress = await signer.getAddress();
const amount = ethers.utils.parseUnits('10', decimals);
if (await token.paused()) throw new Error('Token transfers are currently paused');
if (!await ir.isVerified(recipient)) throw new Error('Recipient is not verified');
const compliance = new ethers.Contract(
await token.compliance(),
['function canTransfer(address,address,uint256) view returns (bool)'],
provider
);
if (!await compliance.canTransfer(senderAddress, recipient, amount)) {
throw new Error('Transfer rejected by compliance rules');
}
const receipt = await (await token.connect(signer).transfer(recipient, amount)).wait();
console.log(receipt.transactionHash);
await (await token.connect(ownerSigner).approve(spender, amount)).wait();
await (await token.connect(spenderSigner)
.transferFrom(ownerAddress, recipient, amount)).wait();
El recibo determina el resultado final.
6.10 Lista de aceptación
Entorno
- Configuración independiente;
- Chain ID estricto;
- Datos de publicación oficial;
- Sin fallback de mainnet a testnet.
Contratos y transacciones
- Nombre, símbolo, decimals, IR y MC correctos;
- Bytecode y ABI correctos;
parseUnits/formatUnits;- Estados enviado/confirmado/fallido;
- Sin actualización final tras fallo ni mint/burn duplicado.
Identidad y seguridad
- IR del activo correcto;
- Diferenciar
containseisVerified; - KYC claro fuera de cadena;
- Mensajes de rechazo comprensibles;
- Sin claves en frontend/repositorio/logs;
- Firmas controladas, proxies y avisos de seguridad.
6.11 Diagnóstico
1. Chain ID
2. RPC
3. Bytecode
4. Token.name / decimals / identityRegistry
5. balance / paused / isFrozen
6. contains / isVerified
7. compliance.canTransfer
8. Rol firmante
9. callStatic / estimateGas
10. Recibo y eventos
Si testnet funciona y mainnet falla, compare red, direcciones, cualificaciones y reglas.