Initial project setup: Add contracts, API definitions, tests, and documentation

- Add Foundry project configuration (foundry.toml, foundry.lock)
- Add Solidity contracts (TokenFactory138, BridgeVault138, ComplianceRegistry, etc.)
- Add API definitions (OpenAPI, GraphQL, gRPC, AsyncAPI)
- Add comprehensive test suite (unit, integration, fuzz, invariants)
- Add API services (REST, GraphQL, orchestrator, packet service)
- Add documentation (ISO20022 mapping, runbooks, adapter guides)
- Add development tools (RBC tool, Swagger UI, mock server)
- Update OpenZeppelin submodules to v5.0.0
This commit is contained in:
defiQUG
2025-12-12 10:59:41 -08:00
parent 26b5aaf932
commit 651ff4f7eb
281 changed files with 24813 additions and 2 deletions

View File

@@ -0,0 +1,333 @@
asyncapi: '3.0.0'
info:
title: eMoney Token Factory Event Bus
version: '1.0.0'
description: |
Event-driven API for eMoney Token Factory system.
Events are published to Kafka/NATS topics for:
- Trigger lifecycle updates
- Lien operations
- Compliance changes
- Packet operations
- Bridge operations
- Policy updates
servers:
kafka:
host: kafka.emoney.example.com
protocol: kafka
description: Production Kafka cluster
security:
- $ref: '#/components/securitySchemes/mtls'
nats:
host: nats.emoney.example.com
protocol: nats
description: Production NATS cluster
security:
- $ref: '#/components/securitySchemes/jwt'
defaultContentType: application/json
channels:
triggers.created:
$ref: './channels/triggers-created.yaml'
triggers.state.updated:
$ref: './channels/triggers-state-updated.yaml'
liens.placed:
$ref: './channels/liens-placed.yaml'
liens.reduced:
$ref: './channels/liens-reduced.yaml'
liens.released:
$ref: './channels/liens-released.yaml'
packets.generated:
$ref: './channels/packets-generated.yaml'
packets.dispatched:
$ref: './channels/packets-dispatched.yaml'
packets.acknowledged:
$ref: './channels/packets-acknowledged.yaml'
bridge.locked:
$ref: './channels/bridge-locked.yaml'
bridge.unlocked:
$ref: './channels/bridge-unlocked.yaml'
compliance.updated:
$ref: './channels/compliance-updated.yaml'
policy.updated:
$ref: './channels/policy-updated.yaml'
components:
securitySchemes:
mtls:
type: mutualTLS
description: Mutual TLS for high-trust adapters
jwt:
type: httpApiKey
in: header
name: Authorization
description: JWT bearer token
scheme: bearer
bearerFormat: JWT
messages:
EventEnvelope:
$ref: '#/components/schemas/EventEnvelope'
TriggerCreated:
$ref: '#/components/schemas/TriggerCreated'
TriggerStateUpdated:
$ref: '#/components/schemas/TriggerStateUpdated'
LienPlaced:
$ref: '#/components/schemas/LienPlaced'
LienReduced:
$ref: '#/components/schemas/LienReduced'
LienReleased:
$ref: '#/components/schemas/LienReleased'
PacketGenerated:
$ref: '#/components/schemas/PacketGenerated'
PacketDispatched:
$ref: '#/components/schemas/PacketDispatched'
PacketAcknowledged:
$ref: '#/components/schemas/PacketAcknowledged'
BridgeLocked:
$ref: '#/components/schemas/BridgeLocked'
BridgeUnlocked:
$ref: '#/components/schemas/BridgeUnlocked'
ComplianceUpdated:
$ref: '#/components/schemas/ComplianceUpdated'
PolicyUpdated:
$ref: '#/components/schemas/PolicyUpdated'
schemas:
EventEnvelope:
type: object
required:
- eventId
- eventType
- occurredAt
- payload
properties:
eventId:
type: string
format: uuid
description: Unique event identifier
eventType:
type: string
description: Event type (e.g., triggers.created)
occurredAt:
type: string
format: date-time
description: Event timestamp
actorRef:
type: string
description: Actor that triggered the event
correlationId:
type: string
description: Correlation ID for tracing
payload:
type: object
description: Event payload (varies by event type)
signatures:
type: array
items:
type: object
properties:
signer:
type: string
signature:
type: string
description: Optional event signatures
TriggerCreated:
type: object
required:
- triggerId
- rail
- msgType
- instructionId
properties:
triggerId:
type: string
rail:
type: string
enum: ["FEDWIRE", "SWIFT", "SEPA", "RTGS"]
msgType:
type: string
instructionId:
type: string
state:
type: string
enum: ["CREATED"]
TriggerStateUpdated:
type: object
required:
- triggerId
- previousState
- newState
properties:
triggerId:
type: string
previousState:
type: string
newState:
type: string
railTxRef:
type: string
nullable: true
LienPlaced:
type: object
required:
- lienId
- debtor
- amount
properties:
lienId:
type: string
debtor:
type: string
amount:
type: string
expiry:
type: integer
priority:
type: integer
authority:
type: string
reasonCode:
type: string
LienReduced:
type: object
required:
- lienId
- reduceBy
- newAmount
properties:
lienId:
type: string
reduceBy:
type: string
newAmount:
type: string
LienReleased:
type: object
required:
- lienId
properties:
lienId:
type: string
PacketGenerated:
type: object
required:
- packetId
- triggerId
- channel
properties:
packetId:
type: string
triggerId:
type: string
channel:
type: string
enum: ["PDF", "AS4", "EMAIL", "PORTAL"]
payloadHash:
type: string
PacketDispatched:
type: object
required:
- packetId
- channel
properties:
packetId:
type: string
channel:
type: string
recipient:
type: string
PacketAcknowledged:
type: object
required:
- packetId
- status
properties:
packetId:
type: string
status:
type: string
enum: ["RECEIVED", "ACCEPTED", "REJECTED"]
ackId:
type: string
BridgeLocked:
type: object
required:
- lockId
- token
- amount
properties:
lockId:
type: string
token:
type: string
amount:
type: string
targetChain:
type: string
targetRecipient:
type: string
BridgeUnlocked:
type: object
required:
- lockId
- token
- amount
properties:
lockId:
type: string
token:
type: string
amount:
type: string
sourceChain:
type: string
sourceTx:
type: string
ComplianceUpdated:
type: object
required:
- refId
- allowed
- frozen
properties:
refId:
type: string
allowed:
type: boolean
frozen:
type: boolean
riskTier:
type: integer
jurisdictionHash:
type: string
PolicyUpdated:
type: object
required:
- token
properties:
token:
type: string
paused:
type: boolean
bridgeOnly:
type: boolean
lienMode:
type: string
enum: ["OFF", "HARD_FREEZE", "ENCUMBERED"]

View File

@@ -0,0 +1,11 @@
description: Bridge lock event
publish:
message:
$ref: '../asyncapi.yaml#/components/messages/EventEnvelope'
bindings:
kafka:
topic: bridge.locked
partitions: 5
replicas: 3
bindingVersion: '0.4.0'

View File

@@ -0,0 +1,11 @@
description: Bridge unlock event
publish:
message:
$ref: '../asyncapi.yaml#/components/messages/EventEnvelope'
bindings:
kafka:
topic: bridge.unlocked
partitions: 5
replicas: 3
bindingVersion: '0.4.0'

View File

@@ -0,0 +1,11 @@
description: Compliance updated event
publish:
message:
$ref: '../asyncapi.yaml#/components/messages/EventEnvelope'
bindings:
kafka:
topic: compliance.updated
partitions: 5
replicas: 3
bindingVersion: '0.4.0'

View File

@@ -0,0 +1,14 @@
description: Lien placed event
subscribe:
message:
$ref: '../asyncapi.yaml#/components/messages/LienPlaced'
publish:
message:
$ref: '../asyncapi.yaml#/components/messages/EventEnvelope'
bindings:
kafka:
topic: liens.placed
partitions: 5
replicas: 3
bindingVersion: '0.4.0'

View File

@@ -0,0 +1,11 @@
description: Lien reduced event
publish:
message:
$ref: '../asyncapi.yaml#/components/messages/EventEnvelope'
bindings:
kafka:
topic: liens.reduced
partitions: 5
replicas: 3
bindingVersion: '0.4.0'

View File

@@ -0,0 +1,11 @@
description: Lien released event
publish:
message:
$ref: '../asyncapi.yaml#/components/messages/EventEnvelope'
bindings:
kafka:
topic: liens.released
partitions: 5
replicas: 3
bindingVersion: '0.4.0'

View File

@@ -0,0 +1,11 @@
description: Packet acknowledged event
publish:
message:
$ref: '../asyncapi.yaml#/components/messages/EventEnvelope'
bindings:
kafka:
topic: packets.acknowledged
partitions: 5
replicas: 3
bindingVersion: '0.4.0'

View File

@@ -0,0 +1,11 @@
description: Packet dispatched event
publish:
message:
$ref: '../asyncapi.yaml#/components/messages/EventEnvelope'
bindings:
kafka:
topic: packets.dispatched
partitions: 5
replicas: 3
bindingVersion: '0.4.0'

View File

@@ -0,0 +1,11 @@
description: Packet generated event
publish:
message:
$ref: '../asyncapi.yaml#/components/messages/EventEnvelope'
bindings:
kafka:
topic: packets.generated
partitions: 5
replicas: 3
bindingVersion: '0.4.0'

View File

@@ -0,0 +1,11 @@
description: Policy updated event
publish:
message:
$ref: '../asyncapi.yaml#/components/messages/EventEnvelope'
bindings:
kafka:
topic: policy.updated
partitions: 5
replicas: 3
bindingVersion: '0.4.0'

View File

@@ -0,0 +1,14 @@
description: Trigger created event
subscribe:
message:
$ref: '../asyncapi.yaml#/components/messages/TriggerCreated'
publish:
message:
$ref: '../asyncapi.yaml#/components/messages/EventEnvelope'
bindings:
kafka:
topic: triggers.created
partitions: 10
replicas: 3
bindingVersion: '0.4.0'

View File

@@ -0,0 +1,14 @@
description: Trigger state updated event
subscribe:
message:
$ref: '../asyncapi.yaml#/components/messages/TriggerStateUpdated'
publish:
message:
$ref: '../asyncapi.yaml#/components/messages/EventEnvelope'
bindings:
kafka:
topic: triggers.state.updated
partitions: 10
replicas: 3
bindingVersion: '0.4.0'

View File

@@ -0,0 +1,554 @@
# GraphQL Schema for eMoney Token Factory API
# This schema provides joined views and subscriptions for complex queries
scalar DateTime
scalar BigInt
scalar Bytes32
type Query {
# Token queries
token(code: String!): Token
tokens(filter: TokenFilter, paging: Paging): TokenConnection!
# Lien queries
lien(lienId: ID!): Lien
liens(filter: LienFilter, paging: Paging): LienConnection!
accountLiens(accountRefId: Bytes32!, active: Boolean): [Lien!]!
accountEncumbrance(accountRefId: Bytes32!, token: String): EncumbranceSummary!
# Compliance queries
compliance(refId: Bytes32!): ComplianceProfile
accountCompliance(accountRefId: Bytes32!): ComplianceProfile
walletCompliance(walletRefId: Bytes32!): ComplianceProfile
# Mapping queries
account(refId: Bytes32!): Account
wallet(refId: Bytes32!): Wallet
accountWallets(accountRefId: Bytes32!): [Wallet!]!
walletAccounts(walletRefId: Bytes32!): [Account!]!
# Trigger queries
trigger(id: ID!): Trigger
triggers(filter: TriggerFilter, paging: Paging): TriggerConnection!
# Packet queries
packet(id: ID!): Packet
packets(filter: PacketFilter, paging: Paging): PacketConnection!
# Bridge queries
bridgeLock(lockId: ID!): BridgeLock
bridgeLocks(filter: BridgeLockFilter, paging: Paging): BridgeLockConnection!
bridgeCorridors: [BridgeCorridor!]!
}
type Mutation {
# Token mutations
deployToken(input: DeployTokenInput!): Token!
updateTokenPolicy(code: String!, input: UpdatePolicyInput!): Token!
mintToken(code: String!, input: MintInput!): TransactionResult!
burnToken(code: String!, input: BurnInput!): TransactionResult!
clawbackToken(code: String!, input: ClawbackInput!): TransactionResult!
forceTransferToken(code: String!, input: ForceTransferInput!): TransactionResult!
# Lien mutations
placeLien(input: PlaceLienInput!): Lien!
reduceLien(lienId: ID!, reduceBy: BigInt!): Lien!
releaseLien(lienId: ID!): Boolean!
# Compliance mutations
setCompliance(refId: Bytes32!, input: SetComplianceInput!): ComplianceProfile!
setFreeze(refId: Bytes32!, frozen: Boolean!): ComplianceProfile!
# Mapping mutations
linkAccountWallet(input: LinkAccountWalletInput!): MappingResult!
unlinkAccountWallet(accountRefId: Bytes32!, walletRefId: Bytes32!): Boolean!
# Trigger mutations
submitInboundMessage(input: SubmitInboundMessageInput!): Trigger!
submitOutboundMessage(input: SubmitOutboundMessageInput!): Trigger!
validateAndLockTrigger(triggerId: ID!): Trigger!
markTriggerSubmitted(triggerId: ID!, railTxRef: String!): Trigger!
confirmTriggerSettled(triggerId: ID!): Trigger!
confirmTriggerRejected(triggerId: ID!, reason: String): Trigger!
# Packet mutations
generatePacket(input: GeneratePacketInput!): Packet!
dispatchPacket(packetId: ID!, input: DispatchPacketInput!): Packet!
acknowledgePacket(packetId: ID!, input: AcknowledgePacketInput!): Packet!
# Bridge mutations
bridgeLock(input: BridgeLockInput!): BridgeLock!
bridgeUnlock(input: BridgeUnlockInput!): BridgeLock!
}
type Subscription {
# Trigger subscriptions
onTriggerStateChanged(triggerId: ID!): Trigger!
onTriggerCreated(filter: TriggerFilter): Trigger!
# Lien subscriptions
onLienChanged(debtorRefId: Bytes32!): Lien!
onLienPlaced: Lien!
onLienReleased: Lien!
# Packet subscriptions
onPacketStatusChanged(packetId: ID!): Packet!
onPacketDispatched: Packet!
onPacketAcknowledged: Packet!
# Compliance subscriptions
onComplianceChanged(refId: Bytes32!): ComplianceProfile!
onFreezeChanged(refId: Bytes32!): ComplianceProfile!
# Policy subscriptions
onPolicyUpdated(token: String!): Token!
}
# Core Types
type Token {
code: String!
address: String!
name: String!
symbol: String!
decimals: Int!
issuer: String!
policy: TokenPolicy!
createdAt: DateTime!
}
type TokenPolicy {
paused: Boolean!
bridgeOnly: Boolean!
bridge: String
lienMode: LienMode!
forceTransferMode: Boolean!
routes: [Rail!]!
}
enum LienMode {
OFF
HARD_FREEZE
ENCUMBERED
}
type Lien {
lienId: ID!
debtor: String!
amount: BigInt!
expiry: Int
priority: Int!
authority: String!
reasonCode: ReasonCode!
active: Boolean!
createdAt: DateTime!
updatedAt: DateTime!
}
type ComplianceProfile {
refId: Bytes32!
allowed: Boolean!
frozen: Boolean!
riskTier: Int
jurisdictionHash: Bytes32
updatedAt: DateTime!
}
type Account {
refId: Bytes32!
provider: AccountProvider!
metadata: JSON
wallets: [Wallet!]!
liens: [Lien!]!
compliance: ComplianceProfile
createdAt: DateTime!
}
type Wallet {
refId: Bytes32!
provider: WalletProvider!
address: String!
metadata: JSON
accounts: [Account!]!
compliance: ComplianceProfile
createdAt: DateTime!
}
enum AccountProvider {
BANK
FINTECH
CUSTODIAN
OTHER
}
enum WalletProvider {
WALLETCONNECT
FIREBLOCKS
METAMASK
OTHER
}
type Trigger {
triggerId: ID!
rail: Rail!
msgType: String!
state: TriggerState!
instructionId: Bytes32!
endToEndId: Bytes32
canonicalMessage: CanonicalMessage
payloadHash: Bytes32!
amount: BigInt!
token: String!
accountRefId: Bytes32!
counterpartyRefId: Bytes32!
railTxRef: String
packets: [Packet!]!
createdAt: DateTime!
updatedAt: DateTime!
}
type CanonicalMessage {
msgType: String!
instructionId: Bytes32!
endToEndId: Bytes32
accountRefId: Bytes32!
counterpartyRefId: Bytes32!
token: String!
amount: BigInt!
currencyCode: Bytes32!
payloadHash: Bytes32!
createdAt: DateTime!
}
type Packet {
packetId: ID!
triggerId: ID!
instructionId: Bytes32!
payloadHash: Bytes32!
channel: PacketChannel!
messageRef: String
status: PacketStatus!
acknowledgements: [Acknowledgement!]!
createdAt: DateTime!
dispatchedAt: DateTime
}
type Acknowledgement {
ackId: String!
receivedAt: DateTime!
status: AcknowledgementStatus!
}
enum PacketChannel {
PDF
AS4
EMAIL
PORTAL
}
enum PacketStatus {
GENERATED
DISPATCHED
DELIVERED
ACKNOWLEDGED
FAILED
}
enum AcknowledgementStatus {
RECEIVED
ACCEPTED
REJECTED
}
type BridgeLock {
lockId: ID!
token: String!
amount: BigInt!
from: String!
targetChain: Bytes32!
targetRecipient: String!
status: BridgeLockStatus!
sourceChain: Bytes32
sourceTx: Bytes32
proof: String
createdAt: DateTime!
unlockedAt: DateTime
}
enum BridgeLockStatus {
LOCKED
UNLOCKED
PENDING
}
type BridgeCorridor {
targetChain: Bytes32!
chainId: String!
verificationMode: VerificationMode!
enabled: Boolean!
}
enum VerificationMode {
LIGHT_CLIENT
MULTISIG
ORACLE
}
enum Rail {
FEDWIRE
SWIFT
SEPA
RTGS
}
enum TriggerState {
CREATED
VALIDATED
SUBMITTED_TO_RAIL
PENDING
SETTLED
REJECTED
CANCELLED
RECALLED
}
enum ReasonCode {
OK
PAUSED
FROM_FROZEN
TO_FROZEN
FROM_NOT_COMPLIANT
TO_NOT_COMPLIANT
LIEN_BLOCK
INSUFF_FREE_BAL
BRIDGE_ONLY
NOT_ALLOWED_ROUTE
UNAUTHORIZED
CONFIG_ERROR
}
# Connection types for pagination
type TokenConnection {
items: [Token!]!
total: Int!
limit: Int!
offset: Int!
}
type LienConnection {
items: [Lien!]!
total: Int!
limit: Int!
offset: Int!
}
type TriggerConnection {
items: [Trigger!]!
total: Int!
limit: Int!
offset: Int!
}
type PacketConnection {
items: [Packet!]!
total: Int!
limit: Int!
offset: Int!
}
type BridgeLockConnection {
items: [BridgeLock!]!
total: Int!
limit: Int!
offset: Int!
}
# Filter types
input TokenFilter {
code: String
issuer: String
}
input LienFilter {
debtor: String
active: Boolean
}
input TriggerFilter {
state: TriggerState
rail: Rail
msgType: String
instructionId: Bytes32
}
input PacketFilter {
triggerId: ID
instructionId: Bytes32
status: PacketStatus
}
input BridgeLockFilter {
token: String
status: BridgeLockStatus
}
input Paging {
limit: Int = 20
offset: Int = 0
}
# Input types
input DeployTokenInput {
name: String!
symbol: String!
decimals: Int!
issuer: String!
defaultLienMode: LienMode = ENCUMBERED
bridgeOnly: Boolean = false
bridge: String
}
input UpdatePolicyInput {
paused: Boolean
bridgeOnly: Boolean
bridge: String
lienMode: LienMode
forceTransferMode: Boolean
routes: [Rail!]
}
input MintInput {
to: String!
amount: BigInt!
reasonCode: ReasonCode
}
input BurnInput {
from: String!
amount: BigInt!
reasonCode: ReasonCode
}
input ClawbackInput {
from: String!
to: String!
amount: BigInt!
reasonCode: ReasonCode
}
input ForceTransferInput {
from: String!
to: String!
amount: BigInt!
reasonCode: ReasonCode
}
input PlaceLienInput {
debtor: String!
amount: BigInt!
expiry: Int
priority: Int
reasonCode: ReasonCode
}
input SetComplianceInput {
allowed: Boolean!
riskTier: Int
jurisdictionHash: Bytes32
}
input LinkAccountWalletInput {
accountRefId: Bytes32!
walletRefId: Bytes32!
}
input SubmitInboundMessageInput {
msgType: String!
instructionId: Bytes32!
endToEndId: Bytes32
payloadHash: Bytes32!
payload: String!
rail: Rail!
}
input SubmitOutboundMessageInput {
msgType: String!
instructionId: Bytes32!
endToEndId: Bytes32
payloadHash: Bytes32!
payload: String!
rail: Rail!
token: String!
amount: BigInt!
accountRefId: Bytes32!
counterpartyRefId: Bytes32!
}
input GeneratePacketInput {
triggerId: ID!
channel: PacketChannel!
options: JSON
}
input DispatchPacketInput {
channel: PacketChannel!
recipient: String
}
input AcknowledgePacketInput {
status: AcknowledgementStatus!
ackId: String
}
input BridgeLockInput {
token: String!
amount: BigInt!
targetChain: Bytes32!
targetRecipient: String!
}
input BridgeUnlockInput {
lockId: ID!
token: String!
to: String!
amount: BigInt!
sourceChain: Bytes32!
sourceTx: Bytes32!
proof: String!
}
# Result types
type TransactionResult {
txHash: Bytes32!
status: TransactionStatus!
blockNumber: Int
}
enum TransactionStatus {
PENDING
SUCCESS
FAILED
}
type MappingResult {
accountRefId: Bytes32!
walletRefId: Bytes32!
linked: Boolean!
createdAt: DateTime!
}
type EncumbranceSummary {
accountRefId: Bytes32!
encumbrances: [TokenEncumbrance!]!
}
type TokenEncumbrance {
token: String!
tokenCode: String!
balance: BigInt!
activeEncumbrance: BigInt!
freeBalance: BigInt!
}
# JSON scalar for metadata
scalar JSON

View File

@@ -0,0 +1,56 @@
syntax = "proto3";
package emoney.adapter.v1;
option go_package = "github.com/emoney/adapter/v1;adapterv1";
// Adapter service for rail integrations (Fedwire/SWIFT/SEPA/RTGS)
service AdapterService {
// Submit message to rail
rpc SubmitToRail(SubmitToRailRequest) returns (SubmitToRailResponse);
// Get rail status
rpc GetRailStatus(GetRailStatusRequest) returns (GetRailStatusResponse);
// Stream rail status updates
rpc StreamRailStatus(StreamRailStatusRequest) returns (stream RailStatusUpdate);
}
message SubmitToRailRequest {
string trigger_id = 1;
string rail = 2;
string msg_type = 3;
bytes payload = 4;
string instruction_id = 5;
}
message SubmitToRailResponse {
string trigger_id = 1;
string rail_tx_ref = 2;
bool accepted = 3;
string error = 4;
}
message GetRailStatusRequest {
string rail_tx_ref = 1;
string rail = 2;
}
message GetRailStatusResponse {
string rail_tx_ref = 1;
string status = 2;
string settlement_date = 3;
string error = 4;
}
message StreamRailStatusRequest {
string trigger_id = 1;
}
message RailStatusUpdate {
string trigger_id = 1;
string rail_tx_ref = 2;
string status = 3;
int64 timestamp = 4;
}

View File

@@ -0,0 +1,100 @@
syntax = "proto3";
package emoney.orchestrator.v1;
option go_package = "github.com/emoney/orchestrator/v1;orchestratorv1";
// Orchestrator service for ISO-20022 message processing and trigger management
service OrchestratorService {
// Validate and lock a trigger
rpc ValidateAndLock(ValidateAndLockRequest) returns (ValidateAndLockResponse);
// Mark trigger as submitted to rail
rpc MarkSubmitted(MarkSubmittedRequest) returns (MarkSubmittedResponse);
// Confirm trigger settled
rpc ConfirmSettled(ConfirmSettledRequest) returns (ConfirmSettledResponse);
// Confirm trigger rejected
rpc ConfirmRejected(ConfirmRejectedRequest) returns (ConfirmRejectedResponse);
// Stream trigger status updates
rpc StreamTriggerStatus(StreamTriggerStatusRequest) returns (stream TriggerStatusUpdate);
// Normalize ISO-20022 message
rpc NormalizeMessage(NormalizeMessageRequest) returns (NormalizeMessageResponse);
}
message ValidateAndLockRequest {
string trigger_id = 1;
}
message ValidateAndLockResponse {
string trigger_id = 1;
bool validated = 2;
string reason_code = 3;
string tx_hash = 4;
}
message MarkSubmittedRequest {
string trigger_id = 1;
string rail_tx_ref = 2;
}
message MarkSubmittedResponse {
string trigger_id = 1;
string state = 2;
}
message ConfirmSettledRequest {
string trigger_id = 1;
string idempotency_key = 2;
}
message ConfirmSettledResponse {
string trigger_id = 1;
string state = 2;
string tx_hash = 3;
}
message ConfirmRejectedRequest {
string trigger_id = 1;
string reason = 2;
string idempotency_key = 3;
}
message ConfirmRejectedResponse {
string trigger_id = 1;
string state = 2;
string tx_hash = 3;
}
message StreamTriggerStatusRequest {
string trigger_id = 1;
}
message TriggerStatusUpdate {
string trigger_id = 1;
string state = 2;
string previous_state = 3;
int64 timestamp = 4;
string rail_tx_ref = 5;
}
message NormalizeMessageRequest {
string msg_type = 1;
bytes payload = 2;
string rail = 3;
}
message NormalizeMessageResponse {
string instruction_id = 1;
string end_to_end_id = 2;
string account_ref_id = 3;
string counterparty_ref_id = 4;
string token = 5;
string amount = 6;
string currency_code = 7;
bytes payload_hash = 8;
}

View File

@@ -0,0 +1,75 @@
syntax = "proto3";
package emoney.packet.v1;
option go_package = "github.com/emoney/packet/v1;packetv1";
// Packet service for non-scheme integration packets
service PacketService {
// Generate packet
rpc GeneratePacket(GeneratePacketRequest) returns (GeneratePacketResponse);
// Dispatch packet
rpc DispatchPacket(DispatchPacketRequest) returns (DispatchPacketResponse);
// Record acknowledgement
rpc RecordAcknowledgement(RecordAcknowledgementRequest) returns (RecordAcknowledgementResponse);
// Get packet status
rpc GetPacketStatus(GetPacketStatusRequest) returns (GetPacketStatusResponse);
}
message GeneratePacketRequest {
string trigger_id = 1;
string channel = 2;
map<string, string> options = 3;
}
message GeneratePacketResponse {
string packet_id = 1;
bytes payload_hash = 2;
string channel = 3;
string download_url = 4;
}
message DispatchPacketRequest {
string packet_id = 1;
string channel = 2;
string recipient = 3;
string idempotency_key = 4;
}
message DispatchPacketResponse {
string packet_id = 1;
string status = 2;
string message_ref = 3;
}
message RecordAcknowledgementRequest {
string packet_id = 1;
string status = 2;
string ack_id = 3;
string idempotency_key = 4;
}
message RecordAcknowledgementResponse {
string packet_id = 1;
bool recorded = 2;
}
message GetPacketStatusRequest {
string packet_id = 1;
}
message GetPacketStatusResponse {
string packet_id = 1;
string status = 2;
repeated Acknowledgement acknowledgements = 3;
}
message Acknowledgement {
string ack_id = 1;
int64 received_at = 2;
string status = 3;
}

View File

@@ -0,0 +1,67 @@
components:
parameters:
IdempotencyKey:
name: Idempotency-Key
in: header
required: false
description: Idempotency key for ensuring request is only processed once
schema:
type: string
format: uuid
TokenCode:
name: code
in: path
required: true
description: Token code (e.g., USDW)
schema:
type: string
pattern: '^[A-Z0-9]{1,10}$'
LienId:
name: lienId
in: path
required: true
description: Lien identifier
schema:
type: string
pattern: '^[0-9]+$'
AccountRefId:
name: accountRefId
in: path
required: true
description: Hashed account reference identifier
schema:
type: string
pattern: '^0x[a-fA-F0-9]{64}$'
WalletRefId:
name: walletRefId
in: path
required: true
description: Hashed wallet reference identifier
schema:
type: string
pattern: '^0x[a-fA-F0-9]{64}$'
TriggerId:
name: triggerId
in: path
required: true
description: Trigger identifier
schema:
type: string
pattern: '^[a-fA-F0-9]{64}$'
PacketId:
name: packetId
in: path
required: true
description: Packet identifier
schema:
type: string
pattern: '^[a-fA-F0-9]{64}$'
LockId:
name: lockId
in: path
required: true
description: Bridge lock identifier
schema:
type: string
pattern: '^[a-fA-F0-9]{64}$'

View File

@@ -0,0 +1,635 @@
components:
schemas:
# Core domain models (reference JSON Schema registry)
Token:
type: object
required:
- code
- address
- name
- symbol
- decimals
- issuer
properties:
code:
type: string
pattern: '^[A-Z0-9]{1,10}$'
address:
type: string
pattern: '^0x[a-fA-F0-9]{40}$'
name:
type: string
symbol:
type: string
decimals:
type: integer
minimum: 0
maximum: 255
issuer:
type: string
pattern: '^0x[a-fA-F0-9]{40}$'
policy:
$ref: '#/components/schemas/TokenPolicy'
createdAt:
type: string
format: date-time
TokenPolicy:
type: object
properties:
paused:
type: boolean
bridgeOnly:
type: boolean
bridge:
type: string
pattern: '^0x[a-fA-F0-9]{40}$'
lienMode:
type: string
enum: ["OFF", "HARD_FREEZE", "ENCUMBERED"]
forceTransferMode:
type: boolean
routes:
type: array
items:
$ref: '#/components/schemas/Rail'
Lien:
type: object
required:
- lienId
- debtor
- amount
- active
properties:
lienId:
type: string
debtor:
type: string
amount:
type: string
expiry:
type: integer
priority:
type: integer
authority:
type: string
reasonCode:
$ref: '#/components/schemas/ReasonCode'
active:
type: boolean
createdAt:
type: string
format: date-time
updatedAt:
type: string
format: date-time
ComplianceProfile:
type: object
required:
- refId
- allowed
- frozen
properties:
refId:
type: string
pattern: '^0x[a-fA-F0-9]{64}$'
allowed:
type: boolean
frozen:
type: boolean
riskTier:
type: integer
minimum: 0
maximum: 255
jurisdictionHash:
type: string
pattern: '^0x[a-fA-F0-9]{64}$'
updatedAt:
type: string
format: date-time
Trigger:
type: object
required:
- triggerId
- rail
- msgType
- state
- instructionId
properties:
triggerId:
type: string
rail:
$ref: '#/components/schemas/Rail'
msgType:
type: string
state:
$ref: '#/components/schemas/TriggerState'
instructionId:
type: string
endToEndId:
type: string
payloadHash:
type: string
amount:
type: string
token:
type: string
accountRefId:
type: string
counterpartyRefId:
type: string
railTxRef:
type: string
nullable: true
createdAt:
type: string
format: date-time
updatedAt:
type: string
format: date-time
Packet:
type: object
required:
- packetId
- payloadHash
- channel
- status
properties:
packetId:
type: string
triggerId:
type: string
instructionId:
type: string
payloadHash:
type: string
channel:
type: string
enum: ["PDF", "AS4", "EMAIL", "PORTAL"]
messageRef:
type: string
nullable: true
status:
type: string
enum: ["GENERATED", "DISPATCHED", "DELIVERED", "ACKNOWLEDGED", "FAILED"]
acknowledgements:
type: array
items:
type: object
properties:
ackId:
type: string
receivedAt:
type: string
format: date-time
status:
type: string
enum: ["RECEIVED", "ACCEPTED", "REJECTED"]
createdAt:
type: string
format: date-time
dispatchedAt:
type: string
format: date-time
nullable: true
BridgeLock:
type: object
required:
- lockId
- token
- amount
- status
properties:
lockId:
type: string
token:
type: string
amount:
type: string
from:
type: string
targetChain:
type: string
targetRecipient:
type: string
status:
type: string
enum: ["LOCKED", "UNLOCKED", "PENDING"]
sourceChain:
type: string
nullable: true
sourceTx:
type: string
nullable: true
proof:
type: string
nullable: true
createdAt:
type: string
format: date-time
unlockedAt:
type: string
format: date-time
nullable: true
AccountRef:
type: object
required:
- refId
properties:
refId:
type: string
provider:
type: string
enum: ["BANK", "FINTECH", "CUSTODIAN", "OTHER"]
metadata:
type: object
createdAt:
type: string
format: date-time
WalletRef:
type: object
required:
- refId
properties:
refId:
type: string
provider:
type: string
enum: ["WALLETCONNECT", "FIREBLOCKS", "METAMASK", "OTHER"]
address:
type: string
metadata:
type: object
createdAt:
type: string
format: date-time
# Enums
ReasonCode:
type: string
enum:
- OK
- PAUSED
- FROM_FROZEN
- TO_FROZEN
- FROM_NOT_COMPLIANT
- TO_NOT_COMPLIANT
- LIEN_BLOCK
- INSUFF_FREE_BAL
- BRIDGE_ONLY
- NOT_ALLOWED_ROUTE
- UNAUTHORIZED
- CONFIG_ERROR
TriggerState:
type: string
enum:
- CREATED
- VALIDATED
- SUBMITTED_TO_RAIL
- PENDING
- SETTLED
- REJECTED
- CANCELLED
- RECALLED
Rail:
type: string
enum:
- FEDWIRE
- SWIFT
- SEPA
- RTGS
# Request/Response models
DeployTokenRequest:
type: object
required:
- name
- symbol
- decimals
- issuer
properties:
name:
type: string
symbol:
type: string
pattern: '^[A-Z0-9]{1,10}$'
decimals:
type: integer
minimum: 0
maximum: 255
issuer:
type: string
pattern: '^0x[a-fA-F0-9]{40}$'
defaultLienMode:
type: string
enum: ["OFF", "HARD_FREEZE", "ENCUMBERED"]
default: "ENCUMBERED"
bridgeOnly:
type: boolean
default: false
bridge:
type: string
pattern: '^0x[a-fA-F0-9]{40}$'
UpdatePolicyRequest:
type: object
properties:
paused:
type: boolean
bridgeOnly:
type: boolean
bridge:
type: string
pattern: '^0x[a-fA-F0-9]{40}$'
lienMode:
type: string
enum: ["OFF", "HARD_FREEZE", "ENCUMBERED"]
forceTransferMode:
type: boolean
routes:
type: array
items:
$ref: '#/components/schemas/Rail'
MintRequest:
type: object
required:
- to
- amount
properties:
to:
type: string
pattern: '^0x[a-fA-F0-9]{40}$'
amount:
type: string
reasonCode:
$ref: '#/components/schemas/ReasonCode'
BurnRequest:
type: object
required:
- from
- amount
properties:
from:
type: string
pattern: '^0x[a-fA-F0-9]{40}$'
amount:
type: string
reasonCode:
$ref: '#/components/schemas/ReasonCode'
ClawbackRequest:
type: object
required:
- from
- to
- amount
properties:
from:
type: string
pattern: '^0x[a-fA-F0-9]{40}$'
to:
type: string
pattern: '^0x[a-fA-F0-9]{40}$'
amount:
type: string
reasonCode:
$ref: '#/components/schemas/ReasonCode'
ForceTransferRequest:
type: object
required:
- from
- to
- amount
properties:
from:
type: string
pattern: '^0x[a-fA-F0-9]{40}$'
to:
type: string
pattern: '^0x[a-fA-F0-9]{40}$'
amount:
type: string
reasonCode:
$ref: '#/components/schemas/ReasonCode'
PlaceLienRequest:
type: object
required:
- debtor
- amount
properties:
debtor:
type: string
amount:
type: string
expiry:
type: integer
minimum: 0
priority:
type: integer
minimum: 0
maximum: 255
reasonCode:
$ref: '#/components/schemas/ReasonCode'
ReduceLienRequest:
type: object
required:
- reduceBy
properties:
reduceBy:
type: string
description: Amount to reduce by
SetComplianceRequest:
type: object
required:
- allowed
properties:
allowed:
type: boolean
riskTier:
type: integer
minimum: 0
maximum: 255
jurisdictionHash:
type: string
pattern: '^0x[a-fA-F0-9]{64}$'
LinkAccountWalletRequest:
type: object
required:
- accountRefId
- walletRefId
properties:
accountRefId:
type: string
pattern: '^0x[a-fA-F0-9]{64}$'
walletRefId:
type: string
pattern: '^0x[a-fA-F0-9]{64}$'
SubmitInboundMessageRequest:
type: object
required:
- msgType
- instructionId
- payloadHash
- payload
properties:
msgType:
type: string
pattern: '^[a-z]+\\.[0-9]{3}$'
instructionId:
type: string
endToEndId:
type: string
payloadHash:
type: string
payload:
type: string
description: ISO-20022 XML payload
rail:
$ref: '#/components/schemas/Rail'
SubmitOutboundMessageRequest:
type: object
required:
- msgType
- instructionId
- payloadHash
- payload
- token
- amount
- accountRefId
- counterpartyRefId
properties:
msgType:
type: string
pattern: '^[a-z]+\\.[0-9]{3}$'
instructionId:
type: string
endToEndId:
type: string
payloadHash:
type: string
payload:
type: string
description: ISO-20022 XML payload
rail:
$ref: '#/components/schemas/Rail'
token:
type: string
pattern: '^0x[a-fA-F0-9]{40}$'
amount:
type: string
accountRefId:
type: string
counterpartyRefId:
type: string
GeneratePacketRequest:
type: object
required:
- triggerId
- channel
properties:
triggerId:
type: string
channel:
type: string
enum: ["PDF", "AS4", "EMAIL", "PORTAL"]
options:
type: object
description: Channel-specific options
BridgeLockRequest:
type: object
required:
- token
- amount
- targetChain
- targetRecipient
properties:
token:
type: string
pattern: '^0x[a-fA-F0-9]{40}$'
amount:
type: string
targetChain:
type: string
targetRecipient:
type: string
pattern: '^0x[a-fA-F0-9]{40}$'
BridgeUnlockRequest:
type: object
required:
- lockId
- token
- to
- amount
- sourceChain
- sourceTx
- proof
properties:
lockId:
type: string
token:
type: string
pattern: '^0x[a-fA-F0-9]{40}$'
to:
type: string
pattern: '^0x[a-fA-F0-9]{40}$'
amount:
type: string
sourceChain:
type: string
sourceTx:
type: string
proof:
type: string
description: Light client proof
TransactionResponse:
type: object
properties:
txHash:
type: string
pattern: '^0x[a-fA-F0-9]{64}$'
status:
type: string
enum: ["PENDING", "SUCCESS", "FAILED"]
blockNumber:
type: integer
nullable: true
Error:
type: object
required:
- code
- message
properties:
code:
type: string
message:
type: string
reasonCode:
$ref: '#/components/schemas/ReasonCode'
details:
type: object
requestId:
type: string

View File

@@ -0,0 +1,12 @@
components:
examples:
DeployUSDW:
summary: Deploy USDW token
value:
name: "USD Wrapped"
symbol: "USDW"
decimals: 18
issuer: "0x1234567890123456789012345678901234567890"
defaultLienMode: "ENCUMBERED"
bridgeOnly: false

View File

@@ -0,0 +1,290 @@
openapi: 3.1.0
info:
title: eMoney Token Factory API
version: 1.0.0
description: |
Comprehensive API for ChainID 138 eMoney Token Factory system.
Features:
- Token deployment and management
- Lien enforcement (hard freeze and encumbered modes)
- Compliance registry
- Account ↔ Wallet mapping
- ISO-20022 message routing
- Payment rail triggers
- Packet generation and dispatch
- Bridge operations
contact:
name: API Support
license:
name: MIT
servers:
- url: https://api.emoney.example.com/v1
description: Production server
- url: https://api-staging.emoney.example.com/v1
description: Staging server
- url: http://localhost:3000/v1
description: Local development server
tags:
- name: Tokens
description: Token deployment and policy management
- name: Liens
description: Lien (encumbrance) management
- name: Compliance
description: Compliance registry operations
- name: Mappings
description: Account ↔ Wallet mapping
- name: Triggers
description: Payment rail trigger management
- name: ISO
description: ISO-20022 message submission
- name: Packets
description: Non-scheme integration packets
- name: Bridge
description: Bridge lock/unlock operations
paths:
/tokens:
$ref: './paths/tokens.yaml#/paths/~1tokens'
/tokens/{code}:
$ref: './paths/tokens.yaml#/paths/~1tokens~1{code}'
/tokens/{code}/policy:
$ref: './paths/tokens.yaml#/paths/~1tokens~1{code}~1policy'
/tokens/{code}/mint:
$ref: './paths/tokens.yaml#/paths/~1tokens~1{code}~1mint'
/tokens/{code}/burn:
$ref: './paths/tokens.yaml#/paths/~1tokens~1{code}~1burn'
/tokens/{code}/clawback:
$ref: './paths/tokens.yaml#/paths/~1tokens~1{code}~1clawback'
/tokens/{code}/force-transfer:
$ref: './paths/tokens.yaml#/paths/~1tokens~1{code}~1force-transfer'
/liens:
$ref: './paths/liens.yaml#/paths/~1liens'
/liens/{lienId}:
$ref: './paths/liens.yaml#/paths/~1liens~1{lienId}'
/accounts/{accountRefId}/liens:
$ref: './paths/liens.yaml#/paths/~1accounts~1{accountRefId}~1liens'
/accounts/{accountRefId}/encumbrance:
$ref: './paths/liens.yaml#/paths/~1accounts~1{accountRefId}~1encumbrance'
/compliance/accounts/{accountRefId}:
$ref: './paths/compliance.yaml#/paths/~1compliance~1accounts~1{accountRefId}'
/compliance/wallets/{walletRefId}:
$ref: './paths/compliance.yaml#/paths/~1compliance~1wallets~1{walletRefId}'
/compliance/{refId}/freeze:
$ref: './paths/compliance.yaml#/paths/~1compliance~1{refId}~1freeze'
/compliance/{refId}:
$ref: './paths/compliance.yaml#/paths/~1compliance~1{refId}'
/mappings/account-wallet/link:
$ref: './paths/mappings.yaml#/paths/~1mappings~1account-wallet~1link'
/mappings/account-wallet/unlink:
$ref: './paths/mappings.yaml#/paths/~1mappings~1account-wallet~1unlink'
/mappings/accounts/{accountRefId}/wallets:
$ref: './paths/mappings.yaml#/paths/~1mappings~1accounts~1{accountRefId}~1wallets'
/mappings/wallets/{walletRefId}/accounts:
$ref: './paths/mappings.yaml#/paths/~1mappings~1wallets~1{walletRefId}~1accounts'
/triggers:
$ref: './paths/triggers.yaml#/paths/~1triggers'
/triggers/{triggerId}:
$ref: './paths/triggers.yaml#/paths/~1triggers~1{triggerId}'
/triggers/{triggerId}/validate-and-lock:
$ref: './paths/triggers.yaml#/paths/~1triggers~1{triggerId}~1validate-and-lock'
/triggers/{triggerId}/mark-submitted:
$ref: './paths/triggers.yaml#/paths/~1triggers~1{triggerId}~1mark-submitted'
/triggers/{triggerId}/confirm-settled:
$ref: './paths/triggers.yaml#/paths/~1triggers~1{triggerId}~1confirm-settled'
/triggers/{triggerId}/confirm-rejected:
$ref: './paths/triggers.yaml#/paths/~1triggers~1{triggerId}~1confirm-rejected'
/iso/inbound:
$ref: './paths/iso.yaml#/paths/~1iso~1inbound'
/iso/outbound:
$ref: './paths/iso.yaml#/paths/~1iso~1outbound'
/packets:
$ref: './paths/packets.yaml#/paths/~1packets'
/packets/{packetId}:
$ref: './paths/packets.yaml#/paths/~1packets~1{packetId}'
/packets/{packetId}/download:
$ref: './paths/packets.yaml#/paths/~1packets~1{packetId}~1download'
/packets/{packetId}/dispatch:
$ref: './paths/packets.yaml#/paths/~1packets~1{packetId}~1dispatch'
/packets/{packetId}/ack:
$ref: './paths/packets.yaml#/paths/~1packets~1{packetId}~1ack'
/bridge/lock:
$ref: './paths/bridge.yaml#/paths/~1bridge~1lock'
/bridge/unlock:
$ref: './paths/bridge.yaml#/paths/~1bridge~1unlock'
/bridge/locks/{lockId}:
$ref: './paths/bridge.yaml#/paths/~1bridge~1locks~1{lockId}'
/bridge/corridors:
$ref: './paths/bridge.yaml#/paths/~1bridge~1corridors'
components:
securitySchemes:
oauth2:
type: oauth2
flows:
clientCredentials:
tokenUrl: /oauth/token
scopes:
tokens:read: Read token information
tokens:write: Deploy and manage tokens
liens:read: Read lien information
liens:write: Manage liens
compliance:read: Read compliance information
compliance:write: Manage compliance
mappings:read: Read account-wallet mappings
mappings:write: Manage mappings
triggers:read: Read trigger information
triggers:write: Manage triggers
packets:read: Read packet information
packets:write: Manage packets
bridge:read: Read bridge information
bridge:write: Manage bridge operations
mtls:
type: mutualTLS
description: Mutual TLS authentication for high-trust adapters
apiKey:
type: apiKey
in: header
name: X-API-Key
description: API key for internal services (optional)
parameters:
IdempotencyKey:
name: Idempotency-Key
in: header
required: false
description: Idempotency key for ensuring request is only processed once
schema:
type: string
format: uuid
TokenCode:
name: code
in: path
required: true
description: Token code (e.g., USDW)
schema:
type: string
pattern: '^[A-Z0-9]{1,10}$'
LienId:
name: lienId
in: path
required: true
description: Lien identifier
schema:
type: string
pattern: '^[0-9]+$'
AccountRefId:
name: accountRefId
in: path
required: true
description: Hashed account reference identifier
schema:
type: string
pattern: '^0x[a-fA-F0-9]{64}$'
WalletRefId:
name: walletRefId
in: path
required: true
description: Hashed wallet reference identifier
schema:
type: string
pattern: '^0x[a-fA-F0-9]{64}$'
TriggerId:
name: triggerId
in: path
required: true
description: Trigger identifier
schema:
type: string
pattern: '^[a-fA-F0-9]{64}$'
PacketId:
name: packetId
in: path
required: true
description: Packet identifier
schema:
type: string
pattern: '^[a-fA-F0-9]{64}$'
LockId:
name: lockId
in: path
required: true
description: Bridge lock identifier
schema:
type: string
pattern: '^[a-fA-F0-9]{64}$'
schemas:
$ref: './components/schemas.yaml'
responses:
BadRequest:
description: Bad request
content:
application/json:
schema:
$ref: './components/schemas.yaml#/components/schemas/Error'
Unauthorized:
description: Unauthorized
content:
application/json:
schema:
$ref: './components/schemas.yaml#/components/schemas/Error'
Forbidden:
description: Forbidden - insufficient permissions
content:
application/json:
schema:
$ref: './components/schemas.yaml#/components/schemas/Error'
NotFound:
description: Resource not found
content:
application/json:
schema:
$ref: './components/schemas.yaml#/components/schemas/Error'
Conflict:
description: Conflict - resource already exists or state conflict
content:
application/json:
schema:
$ref: './components/schemas.yaml#/components/schemas/Error'
UnprocessableEntity:
description: Unprocessable entity - validation error
content:
application/json:
schema:
$ref: './components/schemas.yaml#/components/schemas/Error'
InternalServerError:
description: Internal server error
content:
application/json:
schema:
$ref: './components/schemas.yaml#/components/schemas/Error'
security:
- oauth2: []
x-roles:
ISSUER: "Token issuer operations"
ENFORCEMENT: "Enforcement operations (clawback, force transfer)"
DEBT_AUTHORITY: "Lien management"
COMPLIANCE: "Compliance registry management"
POLICY_OPERATOR: "Policy configuration"
BRIDGE_OPERATOR: "Bridge operations"
x-idempotency:
- POST /tokens
- POST /tokens/{code}/mint
- POST /tokens/{code}/burn
- POST /iso/inbound
- POST /iso/outbound
- POST /triggers/{triggerId}/confirm-settled
- POST /triggers/{triggerId}/confirm-rejected
- POST /packets
- POST /packets/{packetId}/dispatch
- POST /packets/{packetId}/ack
- POST /bridge/unlock

View File

@@ -0,0 +1,113 @@
paths:
/bridge/lock:
post:
summary: Lock tokens for bridge
description: Lock tokens in bridge vault for cross-chain transfer
operationId: bridgeLock
tags:
- Bridge
security:
- oauth2:
- bridge:write
requestBody:
required: true
content:
application/json:
schema:
$ref: '../components/schemas.yaml#/components/schemas/BridgeLockRequest'
responses:
'201':
description: Tokens locked
content:
application/json:
schema:
$ref: '../components/schemas.yaml#/components/schemas/BridgeLock'
'400':
$ref: '../openapi.yaml#/components/responses/BadRequest'
/bridge/unlock:
post:
summary: Unlock tokens from bridge
description: Unlock tokens from bridge vault (requires proof)
operationId: bridgeUnlock
tags:
- Bridge
security:
- oauth2:
- bridge:write
x-roles:
- BRIDGE_OPERATOR
x-idempotency: true
parameters:
- $ref: '../components/parameters.yaml#/components/parameters/IdempotencyKey'
requestBody:
required: true
content:
application/json:
schema:
$ref: '../components/schemas.yaml#/components/schemas/BridgeUnlockRequest'
responses:
'200':
description: Tokens unlocked
content:
application/json:
schema:
$ref: '../components/schemas.yaml#/components/schemas/BridgeLock'
'400':
$ref: '../openapi.yaml#/components/responses/BadRequest'
/bridge/locks/{lockId}:
get:
summary: Get bridge lock status
description: Get bridge lock status by ID
operationId: getBridgeLock
tags:
- Bridge
security:
- oauth2:
- bridge:read
parameters:
- $ref: '../components/parameters.yaml#/components/parameters/LockId'
responses:
'200':
description: Bridge lock details
content:
application/json:
schema:
$ref: '../components/schemas.yaml#/components/schemas/BridgeLock'
'404':
$ref: '../openapi.yaml#/components/responses/NotFound'
/bridge/corridors:
get:
summary: Get supported corridors
description: Get list of supported bridge corridors and verification modes
operationId: getBridgeCorridors
tags:
- Bridge
security:
- oauth2:
- bridge:read
responses:
'200':
description: Supported corridors
content:
application/json:
schema:
type: object
properties:
corridors:
type: array
items:
type: object
properties:
targetChain:
type: string
chainId:
type: string
verificationMode:
type: string
enum: ["LIGHT_CLIENT", "MULTISIG", "ORACLE"]
enabled:
type: boolean

View File

@@ -0,0 +1,167 @@
paths:
/compliance/accounts/{accountRefId}:
put:
summary: Set account compliance
description: Set compliance status for an account
operationId: setAccountCompliance
tags:
- Compliance
security:
- oauth2:
- compliance:write
x-roles:
- COMPLIANCE
parameters:
- $ref: '../components/parameters.yaml#/components/parameters/AccountRefId'
requestBody:
required: true
content:
application/json:
schema:
$ref: '../components/schemas.yaml#/components/schemas/SetComplianceRequest'
responses:
'200':
description: Compliance updated
content:
application/json:
schema:
$ref: '../components/schemas.yaml#/components/schemas/ComplianceProfile'
get:
summary: Get account compliance
description: Get compliance profile for an account
operationId: getAccountCompliance
tags:
- Compliance
security:
- oauth2:
- compliance:read
parameters:
- $ref: '../components/parameters.yaml#/components/parameters/AccountRefId'
responses:
'200':
description: Compliance profile
content:
application/json:
schema:
$ref: '../components/schemas.yaml#/components/schemas/ComplianceProfile'
'404':
$ref: '../openapi.yaml#/components/responses/NotFound'
/compliance/wallets/{walletRefId}:
put:
summary: Set wallet compliance
description: Set compliance status for a wallet
operationId: setWalletCompliance
tags:
- Compliance
security:
- oauth2:
- compliance:write
x-roles:
- COMPLIANCE
parameters:
- $ref: '../components/parameters.yaml#/components/parameters/WalletRefId'
requestBody:
required: true
content:
application/json:
schema:
$ref: '../components/schemas.yaml#/components/schemas/SetComplianceRequest'
responses:
'200':
description: Compliance updated
content:
application/json:
schema:
$ref: '../components/schemas.yaml#/components/schemas/ComplianceProfile'
get:
summary: Get wallet compliance
description: Get compliance profile for a wallet
operationId: getWalletCompliance
tags:
- Compliance
security:
- oauth2:
- compliance:read
parameters:
- $ref: '../components/parameters.yaml#/components/parameters/WalletRefId'
responses:
'200':
description: Compliance profile
content:
application/json:
schema:
$ref: '../components/schemas.yaml#/components/schemas/ComplianceProfile'
'404':
$ref: '../openapi.yaml#/components/responses/NotFound'
/compliance/{refId}/freeze:
put:
summary: Freeze or unfreeze
description: Freeze or unfreeze an account or wallet
operationId: setFreeze
tags:
- Compliance
security:
- oauth2:
- compliance:write
x-roles:
- COMPLIANCE
parameters:
- name: refId
in: path
required: true
schema:
type: string
pattern: '^0x[a-fA-F0-9]{64}$'
description: Account or wallet reference identifier
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- frozen
properties:
frozen:
type: boolean
description: true to freeze, false to unfreeze
responses:
'200':
description: Freeze status updated
content:
application/json:
schema:
$ref: '../components/schemas.yaml#/components/schemas/ComplianceProfile'
/compliance/{refId}:
get:
summary: Get compliance profile
description: Get compliance profile by reference ID (account or wallet)
operationId: getCompliance
tags:
- Compliance
security:
- oauth2:
- compliance:read
parameters:
- name: refId
in: path
required: true
schema:
type: string
pattern: '^0x[a-fA-F0-9]{64}$'
description: Account or wallet reference identifier
responses:
'200':
description: Compliance profile
content:
application/json:
schema:
$ref: '../components/schemas.yaml#/components/schemas/ComplianceProfile'
'404':
$ref: '../openapi.yaml#/components/responses/NotFound'

View File

@@ -0,0 +1,74 @@
paths:
/iso/inbound:
post:
summary: Submit inbound ISO-20022 message
description: Submit an inbound ISO-20022 message (from rail adapter)
operationId: submitInboundMessage
tags:
- ISO
security:
- mtls: []
- oauth2:
- triggers:write
x-roles:
- POLICY_OPERATOR
x-idempotency: true
parameters:
- $ref: '../components/parameters.yaml#/components/parameters/IdempotencyKey'
requestBody:
required: true
content:
application/json:
schema:
$ref: '../components/schemas.yaml#/components/schemas/SubmitInboundMessageRequest'
application/xml:
schema:
type: string
description: ISO-20022 XML payload
responses:
'201':
description: Message submitted and trigger created
content:
application/json:
schema:
$ref: '../components/schemas.yaml#/components/schemas/Trigger'
'400':
$ref: '../openapi.yaml#/components/responses/BadRequest'
'409':
$ref: '../openapi.yaml#/components/responses/Conflict'
/iso/outbound:
post:
summary: Submit outbound ISO-20022 message
description: Submit an outbound ISO-20022 message (from ops/client)
operationId: submitOutboundMessage
tags:
- ISO
security:
- oauth2:
- triggers:write
x-idempotency: true
parameters:
- $ref: '../components/parameters.yaml#/components/parameters/IdempotencyKey'
requestBody:
required: true
content:
application/json:
schema:
$ref: '../components/schemas.yaml#/components/schemas/SubmitOutboundMessageRequest'
application/xml:
schema:
type: string
description: ISO-20022 XML payload
responses:
'201':
description: Message submitted and trigger created
content:
application/json:
schema:
$ref: '../components/schemas.yaml#/components/schemas/Trigger'
'400':
$ref: '../openapi.yaml#/components/responses/BadRequest'
'409':
$ref: '../openapi.yaml#/components/responses/Conflict'

View File

@@ -0,0 +1,238 @@
paths:
/liens:
post:
summary: Place a lien
description: Place a lien (encumbrance) on an account
operationId: placeLien
tags:
- Liens
security:
- oauth2:
- liens:write
x-roles:
- DEBT_AUTHORITY
requestBody:
required: true
content:
application/json:
schema:
$ref: '../components/schemas.yaml#/components/schemas/PlaceLienRequest'
responses:
'201':
description: Lien placed successfully
content:
application/json:
schema:
$ref: '../components/schemas.yaml#/components/schemas/Lien'
'400':
$ref: '../openapi.yaml#/components/responses/BadRequest'
'403':
$ref: '../openapi.yaml#/components/responses/Forbidden'
get:
summary: List liens
description: List liens with optional filtering
operationId: listLiens
tags:
- Liens
security:
- oauth2:
- liens:read
parameters:
- name: debtor
in: query
schema:
type: string
pattern: '^(0x[a-fA-F0-9]{40}|0x[a-fA-F0-9]{64})$'
description: Filter by debtor address or account reference
- name: active
in: query
schema:
type: boolean
description: Filter by active status
- name: limit
in: query
schema:
type: integer
minimum: 1
maximum: 100
default: 20
- name: offset
in: query
schema:
type: integer
minimum: 0
default: 0
responses:
'200':
description: List of liens
content:
application/json:
schema:
type: object
properties:
items:
type: array
items:
$ref: '../components/schemas.yaml#/components/schemas/Lien'
total:
type: integer
limit:
type: integer
offset:
type: integer
/liens/{lienId}:
get:
summary: Get lien
description: Get lien details by ID
operationId: getLien
tags:
- Liens
security:
- oauth2:
- liens:read
parameters:
- $ref: '../components/parameters.yaml#/components/parameters/LienId'
responses:
'200':
description: Lien details
content:
application/json:
schema:
$ref: '../components/schemas.yaml#/components/schemas/Lien'
'404':
$ref: '../openapi.yaml#/components/responses/NotFound'
patch:
summary: Reduce lien
description: Reduce lien amount
operationId: reduceLien
tags:
- Liens
security:
- oauth2:
- liens:write
x-roles:
- DEBT_AUTHORITY
parameters:
- $ref: '../components/parameters.yaml#/components/parameters/LienId'
requestBody:
required: true
content:
application/json:
schema:
$ref: '../components/schemas.yaml#/components/schemas/ReduceLienRequest'
responses:
'200':
description: Lien reduced
content:
application/json:
schema:
$ref: '../components/schemas.yaml#/components/schemas/Lien'
delete:
summary: Release lien
description: Release (remove) a lien
operationId: releaseLien
tags:
- Liens
security:
- oauth2:
- liens:write
x-roles:
- DEBT_AUTHORITY
parameters:
- $ref: '../components/parameters.yaml#/components/parameters/LienId'
responses:
'200':
description: Lien released
content:
application/json:
schema:
type: object
properties:
lienId:
type: string
released:
type: boolean
/accounts/{accountRefId}/liens:
get:
summary: List liens for account
description: Get all liens for a specific account
operationId: getAccountLiens
tags:
- Liens
security:
- oauth2:
- liens:read
parameters:
- $ref: '../components/parameters.yaml#/components/parameters/AccountRefId'
- name: active
in: query
schema:
type: boolean
description: Filter by active status
responses:
'200':
description: List of liens
content:
application/json:
schema:
type: object
properties:
accountRefId:
type: string
liens:
type: array
items:
$ref: '../components/schemas.yaml#/components/schemas/Lien'
activeEncumbrance:
type: string
description: Total active encumbrance amount
/accounts/{accountRefId}/encumbrance:
get:
summary: Get encumbrance summary
description: Get active encumbrance and free balance for an account by token
operationId: getEncumbrance
tags:
- Liens
security:
- oauth2:
- liens:read
parameters:
- $ref: '../components/parameters.yaml#/components/parameters/AccountRefId'
- name: token
in: query
schema:
type: string
pattern: '^0x[a-fA-F0-9]{40}$'
description: Token address (optional, returns for all tokens if omitted)
responses:
'200':
description: Encumbrance summary
content:
application/json:
schema:
type: object
properties:
accountRefId:
type: string
encumbrances:
type: array
items:
type: object
properties:
token:
type: string
tokenCode:
type: string
balance:
type: string
activeEncumbrance:
type: string
freeBalance:
type: string

View File

@@ -0,0 +1,130 @@
paths:
/mappings/account-wallet/link:
post:
summary: Link account to wallet
description: Create a mapping between an account reference and a wallet reference
operationId: linkAccountWallet
tags:
- Mappings
security:
- oauth2:
- mappings:write
requestBody:
required: true
content:
application/json:
schema:
$ref: '../components/schemas.yaml#/components/schemas/LinkAccountWalletRequest'
responses:
'201':
description: Mapping created
content:
application/json:
schema:
type: object
properties:
accountRefId:
type: string
walletRefId:
type: string
linked:
type: boolean
createdAt:
type: string
format: date-time
/mappings/account-wallet/unlink:
post:
summary: Unlink account from wallet
description: Remove a mapping between an account reference and a wallet reference
operationId: unlinkAccountWallet
tags:
- Mappings
security:
- oauth2:
- mappings:write
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- accountRefId
- walletRefId
properties:
accountRefId:
type: string
pattern: '^0x[a-fA-F0-9]{64}$'
walletRefId:
type: string
pattern: '^0x[a-fA-F0-9]{64}$'
responses:
'200':
description: Mapping removed
content:
application/json:
schema:
type: object
properties:
accountRefId:
type: string
walletRefId:
type: string
unlinked:
type: boolean
/mappings/accounts/{accountRefId}/wallets:
get:
summary: Get wallets for account
description: Get all wallet references linked to an account reference
operationId: getAccountWallets
tags:
- Mappings
security:
- oauth2:
- mappings:read
parameters:
- $ref: '../components/parameters.yaml#/components/parameters/AccountRefId'
responses:
'200':
description: List of wallet references
content:
application/json:
schema:
type: object
properties:
accountRefId:
type: string
wallets:
type: array
items:
$ref: '../components/schemas.yaml#/components/schemas/WalletRef'
/mappings/wallets/{walletRefId}/accounts:
get:
summary: Get accounts for wallet
description: Get all account references linked to a wallet reference
operationId: getWalletAccounts
tags:
- Mappings
security:
- oauth2:
- mappings:read
parameters:
- $ref: '../components/parameters.yaml#/components/parameters/WalletRefId'
responses:
'200':
description: List of account references
content:
application/json:
schema:
type: object
properties:
walletRefId:
type: string
accounts:
type: array
items:
$ref: '../components/schemas.yaml#/components/schemas/AccountRef'

View File

@@ -0,0 +1,206 @@
paths:
/packets:
post:
summary: Generate packet
description: Generate a non-scheme integration packet (PDF + sidecars)
operationId: generatePacket
tags:
- Packets
security:
- oauth2:
- packets:write
x-idempotency: true
parameters:
- $ref: '../components/parameters.yaml#/components/parameters/IdempotencyKey'
requestBody:
required: true
content:
application/json:
schema:
$ref: '../components/schemas.yaml#/components/schemas/GeneratePacketRequest'
responses:
'201':
description: Packet generated
content:
application/json:
schema:
$ref: '../components/schemas.yaml#/components/schemas/Packet'
get:
summary: List packets
description: List packets with optional filtering
operationId: listPackets
tags:
- Packets
security:
- oauth2:
- packets:read
parameters:
- name: triggerId
in: query
schema:
type: string
pattern: '^[a-fA-F0-9]{64}$'
description: Filter by trigger ID
- name: instructionId
in: query
schema:
type: string
pattern: '^[a-fA-F0-9]{64}$'
description: Filter by instruction ID
- name: status
in: query
schema:
type: string
enum: ["GENERATED", "DISPATCHED", "DELIVERED", "ACKNOWLEDGED", "FAILED"]
- name: limit
in: query
schema:
type: integer
minimum: 1
maximum: 100
default: 20
- name: offset
in: query
schema:
type: integer
minimum: 0
default: 0
responses:
'200':
description: List of packets
content:
application/json:
schema:
type: object
properties:
items:
type: array
items:
$ref: '../components/schemas.yaml#/components/schemas/Packet'
total:
type: integer
limit:
type: integer
offset:
type: integer
/packets/{packetId}:
get:
summary: Get packet
description: Get packet metadata and hashes
operationId: getPacket
tags:
- Packets
security:
- oauth2:
- packets:read
parameters:
- $ref: '../components/parameters.yaml#/components/parameters/PacketId'
responses:
'200':
description: Packet metadata
content:
application/json:
schema:
$ref: '../components/schemas.yaml#/components/schemas/Packet'
'404':
$ref: '../openapi.yaml#/components/responses/NotFound'
/packets/{packetId}/download:
get:
summary: Download packet
description: Download packet file (PDF, etc.) - auth controlled
operationId: downloadPacket
tags:
- Packets
security:
- oauth2:
- packets:read
parameters:
- $ref: '../components/parameters.yaml#/components/parameters/PacketId'
responses:
'200':
description: Packet file
content:
application/pdf:
schema:
type: string
format: binary
'404':
$ref: '../openapi.yaml#/components/responses/NotFound'
/packets/{packetId}/dispatch:
post:
summary: Dispatch packet
description: Dispatch packet via email/AS4/portal
operationId: dispatchPacket
tags:
- Packets
security:
- oauth2:
- packets:write
x-idempotency: true
parameters:
- $ref: '../components/parameters.yaml#/components/parameters/PacketId'
- $ref: '../components/parameters.yaml#/components/parameters/IdempotencyKey'
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- channel
properties:
channel:
type: string
enum: ["EMAIL", "AS4", "PORTAL"]
recipient:
type: string
description: Recipient address/identifier
responses:
'200':
description: Packet dispatched
content:
application/json:
schema:
$ref: '../components/schemas.yaml#/components/schemas/Packet'
/packets/{packetId}/ack:
post:
summary: Record packet acknowledgement
description: Record an acknowledgement/receipt for a packet
operationId: acknowledgePacket
tags:
- Packets
security:
- oauth2:
- packets:write
x-idempotency: true
parameters:
- $ref: '../components/parameters.yaml#/components/parameters/PacketId'
- $ref: '../components/parameters.yaml#/components/parameters/IdempotencyKey'
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- status
properties:
status:
type: string
enum: ["RECEIVED", "ACCEPTED", "REJECTED"]
ackId:
type: string
description: Acknowledgement identifier
responses:
'200':
description: Acknowledgement recorded
content:
application/json:
schema:
$ref: '../components/schemas.yaml#/components/schemas/Packet'

View File

@@ -0,0 +1,266 @@
paths:
/tokens:
post:
summary: Deploy a new token
description: Deploy a new eMoney token on ChainID 138
operationId: deployToken
tags:
- Tokens
security:
- oauth2:
- tokens:write
x-roles:
- TOKEN_DEPLOYER
x-idempotency: true
parameters:
- $ref: '../components/parameters.yaml#/components/parameters/IdempotencyKey'
requestBody:
required: true
content:
application/json:
schema:
$ref: '../components/schemas.yaml#/components/schemas/DeployTokenRequest'
examples:
usdw:
$ref: '../examples/tokens.yaml#/components/examples/DeployUSDW'
responses:
'201':
description: Token deployed successfully
content:
application/json:
schema:
$ref: '../components/schemas.yaml#/components/schemas/Token'
'400':
$ref: '../openapi.yaml#/components/responses/BadRequest'
'401':
$ref: '../openapi.yaml#/components/responses/Unauthorized'
'403':
$ref: '../openapi.yaml#/components/responses/Forbidden'
'409':
$ref: '../openapi.yaml#/components/responses/Conflict'
get:
summary: List tokens
description: List all deployed tokens with optional filtering
operationId: listTokens
tags:
- Tokens
security:
- oauth2:
- tokens:read
parameters:
- name: code
in: query
schema:
type: string
pattern: '^[A-Z0-9]{1,10}$'
description: Filter by token code
- name: issuer
in: query
schema:
type: string
pattern: '^0x[a-fA-F0-9]{40}$'
description: Filter by issuer address
- name: limit
in: query
schema:
type: integer
minimum: 1
maximum: 100
default: 20
description: Maximum number of results
- name: offset
in: query
schema:
type: integer
minimum: 0
default: 0
description: Pagination offset
responses:
'200':
description: List of tokens
content:
application/json:
schema:
type: object
properties:
items:
type: array
items:
$ref: '../components/schemas.yaml#/components/schemas/Token'
total:
type: integer
limit:
type: integer
offset:
type: integer
/tokens/{code}:
get:
summary: Get token metadata
description: Get token metadata and configuration by code
operationId: getToken
tags:
- Tokens
security:
- oauth2:
- tokens:read
parameters:
- $ref: '../components/parameters.yaml#/components/parameters/TokenCode'
responses:
'200':
description: Token metadata
content:
application/json:
schema:
$ref: '../components/schemas.yaml#/components/schemas/Token'
'404':
$ref: '../openapi.yaml#/components/responses/NotFound'
patch:
summary: Update token policy
description: Update token policy configuration (pause, lienMode, bridgeOnly, etc.)
operationId: updateTokenPolicy
tags:
- Tokens
security:
- oauth2:
- tokens:write
x-roles:
- POLICY_OPERATOR
parameters:
- $ref: '../components/parameters.yaml#/components/parameters/TokenCode'
requestBody:
required: true
content:
application/json:
schema:
$ref: '../components/schemas.yaml#/components/schemas/UpdatePolicyRequest'
responses:
'200':
description: Policy updated
content:
application/json:
schema:
$ref: '../components/schemas.yaml#/components/schemas/Token'
/tokens/{code}/mint:
post:
summary: Mint tokens
description: Mint new tokens to an address (requires ISSUER_ROLE)
operationId: mintTokens
tags:
- Tokens
security:
- oauth2:
- tokens:write
x-roles:
- ISSUER
x-idempotency: true
parameters:
- $ref: '../components/parameters.yaml#/components/parameters/TokenCode'
- $ref: '../components/parameters.yaml#/components/parameters/IdempotencyKey'
requestBody:
required: true
content:
application/json:
schema:
$ref: '../components/schemas.yaml#/components/schemas/MintRequest'
responses:
'200':
description: Tokens minted
content:
application/json:
schema:
$ref: '../components/schemas.yaml#/components/schemas/TransactionResponse'
/tokens/{code}/burn:
post:
summary: Burn tokens
description: Burn tokens from an address (requires ISSUER_ROLE)
operationId: burnTokens
tags:
- Tokens
security:
- oauth2:
- tokens:write
x-roles:
- ISSUER
x-idempotency: true
parameters:
- $ref: '../components/parameters.yaml#/components/parameters/TokenCode'
- $ref: '../components/parameters.yaml#/components/parameters/IdempotencyKey'
requestBody:
required: true
content:
application/json:
schema:
$ref: '../components/schemas.yaml#/components/schemas/BurnRequest'
responses:
'200':
description: Tokens burned
content:
application/json:
schema:
$ref: '../components/schemas.yaml#/components/schemas/TransactionResponse'
/tokens/{code}/clawback:
post:
summary: Clawback tokens
description: Clawback tokens from an address (requires ENFORCEMENT_ROLE)
operationId: clawbackTokens
tags:
- Tokens
security:
- oauth2:
- tokens:write
x-roles:
- ENFORCEMENT
x-idempotency: true
parameters:
- $ref: '../components/parameters.yaml#/components/parameters/TokenCode'
- $ref: '../components/parameters.yaml#/components/parameters/IdempotencyKey'
requestBody:
required: true
content:
application/json:
schema:
$ref: '../components/schemas.yaml#/components/schemas/ClawbackRequest'
responses:
'200':
description: Tokens clawed back
content:
application/json:
schema:
$ref: '../components/schemas.yaml#/components/schemas/TransactionResponse'
/tokens/{code}/force-transfer:
post:
summary: Force transfer tokens
description: Force transfer tokens between addresses (requires ENFORCEMENT_ROLE and forceTransferMode)
operationId: forceTransferTokens
tags:
- Tokens
security:
- oauth2:
- tokens:write
x-roles:
- ENFORCEMENT
x-idempotency: true
parameters:
- $ref: '../components/parameters.yaml#/components/parameters/TokenCode'
- $ref: '../components/parameters.yaml#/components/parameters/IdempotencyKey'
requestBody:
required: true
content:
application/json:
schema:
$ref: '../components/schemas.yaml#/components/schemas/ForceTransferRequest'
responses:
'200':
description: Tokens force transferred
content:
application/json:
schema:
$ref: '../components/schemas.yaml#/components/schemas/TransactionResponse'

View File

@@ -0,0 +1,206 @@
paths:
/triggers:
get:
summary: List triggers
description: List payment rail triggers with filtering
operationId: listTriggers
tags:
- Triggers
security:
- oauth2:
- triggers:read
parameters:
- name: state
in: query
schema:
$ref: '../components/schemas.yaml#/components/schemas/TriggerState'
description: Filter by trigger state
- name: rail
in: query
schema:
$ref: '../components/schemas.yaml#/components/schemas/Rail'
description: Filter by payment rail
- name: msgType
in: query
schema:
type: string
pattern: '^[a-z]+\\.[0-9]{3}$'
description: Filter by ISO-20022 message type
- name: instructionId
in: query
schema:
type: string
pattern: '^[a-fA-F0-9]{64}$'
description: Filter by instruction ID
- name: limit
in: query
schema:
type: integer
minimum: 1
maximum: 100
default: 20
- name: offset
in: query
schema:
type: integer
minimum: 0
default: 0
responses:
'200':
description: List of triggers
content:
application/json:
schema:
type: object
properties:
items:
type: array
items:
$ref: '../components/schemas.yaml#/components/schemas/Trigger'
total:
type: integer
limit:
type: integer
offset:
type: integer
/triggers/{triggerId}:
get:
summary: Get trigger
description: Get trigger details by ID
operationId: getTrigger
tags:
- Triggers
security:
- oauth2:
- triggers:read
parameters:
- $ref: '../components/parameters.yaml#/components/parameters/TriggerId'
responses:
'200':
description: Trigger details
content:
application/json:
schema:
$ref: '../components/schemas.yaml#/components/schemas/Trigger'
'404':
$ref: '../openapi.yaml#/components/responses/NotFound'
/triggers/{triggerId}/validate-and-lock:
post:
summary: Validate and lock trigger
description: Orchestrator step - validate trigger and lock funds
operationId: validateAndLockTrigger
tags:
- Triggers
security:
- oauth2:
- triggers:write
x-roles:
- POLICY_OPERATOR
parameters:
- $ref: '../components/parameters.yaml#/components/parameters/TriggerId'
responses:
'200':
description: Trigger validated and locked
content:
application/json:
schema:
$ref: '../components/schemas.yaml#/components/schemas/Trigger'
'400':
$ref: '../openapi.yaml#/components/responses/BadRequest'
'409':
$ref: '../openapi.yaml#/components/responses/Conflict'
/triggers/{triggerId}/mark-submitted:
post:
summary: Mark trigger as submitted
description: Mark trigger as submitted to rail (includes railTxRef)
operationId: markTriggerSubmitted
tags:
- Triggers
security:
- oauth2:
- triggers:write
x-roles:
- POLICY_OPERATOR
parameters:
- $ref: '../components/parameters.yaml#/components/parameters/TriggerId'
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- railTxRef
properties:
railTxRef:
type: string
description: Rail transaction reference
responses:
'200':
description: Trigger marked as submitted
content:
application/json:
schema:
$ref: '../components/schemas.yaml#/components/schemas/Trigger'
/triggers/{triggerId}/confirm-settled:
post:
summary: Confirm trigger settled
description: Confirm trigger has settled on the rail
operationId: confirmTriggerSettled
tags:
- Triggers
security:
- oauth2:
- triggers:write
x-roles:
- POLICY_OPERATOR
x-idempotency: true
parameters:
- $ref: '../components/parameters.yaml#/components/parameters/TriggerId'
- $ref: '../components/parameters.yaml#/components/parameters/IdempotencyKey'
responses:
'200':
description: Trigger confirmed as settled
content:
application/json:
schema:
$ref: '../components/schemas.yaml#/components/schemas/Trigger'
/triggers/{triggerId}/confirm-rejected:
post:
summary: Confirm trigger rejected
description: Confirm trigger was rejected on the rail
operationId: confirmTriggerRejected
tags:
- Triggers
security:
- oauth2:
- triggers:write
x-roles:
- POLICY_OPERATOR
x-idempotency: true
parameters:
- $ref: '../components/parameters.yaml#/components/parameters/TriggerId'
- $ref: '../components/parameters.yaml#/components/parameters/IdempotencyKey'
requestBody:
required: false
content:
application/json:
schema:
type: object
properties:
reason:
type: string
description: Rejection reason
responses:
'200':
description: Trigger confirmed as rejected
content:
application/json:
schema:
$ref: '../components/schemas.yaml#/components/schemas/Trigger'

View File

@@ -0,0 +1,429 @@
{
"info": {
"name": "eMoney Token Factory API",
"description": "Complete API collection for eMoney Token Factory",
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
"_exporter_id": "emoney-api"
},
"item": [
{
"name": "Tokens",
"item": [
{
"name": "Deploy Token",
"event": [
{
"listen": "prerequest",
"script": {
"exec": [
"// Get OAuth2 token",
"pm.sendRequest({",
" url: pm.environment.get('auth_url') + '/oauth/token',",
" method: 'POST',",
" header: { 'Content-Type': 'application/json' },",
" body: {",
" mode: 'raw',",
" raw: JSON.stringify({",
" grant_type: 'client_credentials',",
" client_id: pm.environment.get('client_id'),",
" client_secret: pm.environment.get('client_secret')",
" })",
" }",
"}, function (err, res) {",
" if (res.json().access_token) {",
" pm.environment.set('access_token', res.json().access_token);",
" }",
"});",
"",
"// Generate idempotency key",
"pm.environment.set('idempotency_key', pm.variables.replaceIn('{{$randomUUID}}'));"
]
}
}
],
"request": {
"method": "POST",
"header": [
{
"key": "Authorization",
"value": "Bearer {{access_token}}",
"type": "text"
},
{
"key": "Idempotency-Key",
"value": "{{idempotency_key}}",
"type": "text"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"name\": \"USD Wrapped\",\n \"symbol\": \"USDW\",\n \"decimals\": 18,\n \"issuer\": \"0x1234567890123456789012345678901234567890\",\n \"defaultLienMode\": \"ENCUMBERED\"\n}"
},
"url": {
"raw": "{{base_url}}/v1/tokens",
"host": ["{{base_url}}"],
"path": ["v1", "tokens"]
}
}
},
{
"name": "List Tokens",
"request": {
"method": "GET",
"header": [
{
"key": "Authorization",
"value": "Bearer {{access_token}}",
"type": "text"
}
],
"url": {
"raw": "{{base_url}}/v1/tokens?limit=20&offset=0",
"host": ["{{base_url}}"],
"path": ["v1", "tokens"],
"query": [
{
"key": "limit",
"value": "20"
},
{
"key": "offset",
"value": "0"
}
]
}
}
},
{
"name": "Get Token",
"request": {
"method": "GET",
"header": [
{
"key": "Authorization",
"value": "Bearer {{access_token}}",
"type": "text"
}
],
"url": {
"raw": "{{base_url}}/v1/tokens/USDW",
"host": ["{{base_url}}"],
"path": ["v1", "tokens", "USDW"]
}
}
},
{
"name": "Update Token Policy",
"request": {
"method": "PATCH",
"header": [
{
"key": "Authorization",
"value": "Bearer {{access_token}}",
"type": "text"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"paused\": false,\n \"lienMode\": \"ENCUMBERED\"\n}"
},
"url": {
"raw": "{{base_url}}/v1/tokens/USDW/policy",
"host": ["{{base_url}}"],
"path": ["v1", "tokens", "USDW", "policy"]
}
}
}
]
},
{
"name": "Liens",
"item": [
{
"name": "Place Lien",
"request": {
"method": "POST",
"header": [
{
"key": "Authorization",
"value": "Bearer {{access_token}}",
"type": "text"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"debtor\": \"0xabcdefabcdefabcdefabcdefabcdefabcdefabcd\",\n \"amount\": \"1000000000000000000\",\n \"priority\": 1,\n \"reasonCode\": \"DEBT_ENFORCEMENT\"\n}"
},
"url": {
"raw": "{{base_url}}/v1/liens",
"host": ["{{base_url}}"],
"path": ["v1", "liens"]
}
}
},
{
"name": "Get Lien",
"request": {
"method": "GET",
"header": [
{
"key": "Authorization",
"value": "Bearer {{access_token}}",
"type": "text"
}
],
"url": {
"raw": "{{base_url}}/v1/liens/123",
"host": ["{{base_url}}"],
"path": ["v1", "liens", "123"]
}
}
},
{
"name": "Reduce Lien",
"request": {
"method": "PATCH",
"header": [
{
"key": "Authorization",
"value": "Bearer {{access_token}}",
"type": "text"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"reduceBy\": \"500000000000000000\"\n}"
},
"url": {
"raw": "{{base_url}}/v1/liens/123",
"host": ["{{base_url}}"],
"path": ["v1", "liens", "123"]
}
}
},
{
"name": "Release Lien",
"request": {
"method": "DELETE",
"header": [
{
"key": "Authorization",
"value": "Bearer {{access_token}}",
"type": "text"
}
],
"url": {
"raw": "{{base_url}}/v1/liens/123",
"host": ["{{base_url}}"],
"path": ["v1", "liens", "123"]
}
}
}
]
},
{
"name": "Compliance",
"item": [
{
"name": "Set Account Compliance",
"request": {
"method": "PUT",
"header": [
{
"key": "Authorization",
"value": "Bearer {{access_token}}",
"type": "text"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"allowed\": true,\n \"riskTier\": 1,\n \"jurisdictionHash\": \"0x0000000000000000000000000000000000000000000000000000000000000001\"\n}"
},
"url": {
"raw": "{{base_url}}/v1/compliance/accounts/0xabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcd",
"host": ["{{base_url}}"],
"path": ["v1", "compliance", "accounts", "0xabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcd"]
}
}
},
{
"name": "Freeze Account",
"request": {
"method": "PUT",
"header": [
{
"key": "Authorization",
"value": "Bearer {{access_token}}",
"type": "text"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"frozen\": true\n}"
},
"url": {
"raw": "{{base_url}}/v1/compliance/0xabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcd/freeze",
"host": ["{{base_url}}"],
"path": ["v1", "compliance", "0xabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcd", "freeze"]
}
}
}
]
},
{
"name": "Triggers",
"item": [
{
"name": "List Triggers",
"request": {
"method": "GET",
"header": [
{
"key": "Authorization",
"value": "Bearer {{access_token}}",
"type": "text"
}
],
"url": {
"raw": "{{base_url}}/v1/triggers?state=PENDING&limit=20",
"host": ["{{base_url}}"],
"path": ["v1", "triggers"],
"query": [
{
"key": "state",
"value": "PENDING"
},
{
"key": "limit",
"value": "20"
}
]
}
}
},
{
"name": "Get Trigger",
"request": {
"method": "GET",
"header": [
{
"key": "Authorization",
"value": "Bearer {{access_token}}",
"type": "text"
}
],
"url": {
"raw": "{{base_url}}/v1/triggers/abc123def456",
"host": ["{{base_url}}"],
"path": ["v1", "triggers", "abc123def456"]
}
}
}
]
},
{
"name": "ISO-20022",
"item": [
{
"name": "Submit Inbound Message",
"request": {
"method": "POST",
"header": [
{
"key": "Authorization",
"value": "Bearer {{access_token}}",
"type": "text"
},
{
"key": "Idempotency-Key",
"value": "{{idempotency_key}}",
"type": "text"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"msgType\": \"pacs.008\",\n \"instructionId\": \"0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef\",\n \"payloadHash\": \"0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890ab\",\n \"payload\": \"<Document>...</Document>\",\n \"rail\": \"FEDWIRE\"\n}"
},
"url": {
"raw": "{{base_url}}/v1/iso/inbound",
"host": ["{{base_url}}"],
"path": ["v1", "iso", "inbound"]
}
}
}
]
},
{
"name": "Packets",
"item": [
{
"name": "Generate Packet",
"request": {
"method": "POST",
"header": [
{
"key": "Authorization",
"value": "Bearer {{access_token}}",
"type": "text"
},
{
"key": "Idempotency-Key",
"value": "{{idempotency_key}}",
"type": "text"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"triggerId\": \"abc123def456\",\n \"channel\": \"PDF\"\n}"
},
"url": {
"raw": "{{base_url}}/v1/packets",
"host": ["{{base_url}}"],
"path": ["v1", "packets"]
}
}
}
]
},
{
"name": "Bridge",
"item": [
{
"name": "Lock Tokens",
"request": {
"method": "POST",
"header": [
{
"key": "Authorization",
"value": "Bearer {{access_token}}",
"type": "text"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"token\": \"0x1234567890123456789012345678901234567890\",\n \"amount\": \"1000000000000000000\",\n \"targetChain\": \"0x0000000000000000000000000000000000000000000000000000000000000001\",\n \"targetRecipient\": \"0xabcdefabcdefabcdefabcdefabcdefabcdefabcd\"\n}"
},
"url": {
"raw": "{{base_url}}/v1/bridge/lock",
"host": ["{{base_url}}"],
"path": ["v1", "bridge", "lock"]
}
}
}
]
}
],
"variable": [
{
"key": "base_url",
"value": "http://localhost:3000",
"type": "string"
},
{
"key": "auth_url",
"value": "http://localhost:3000",
"type": "string"
}
]
}

View File

@@ -0,0 +1,32 @@
{
"id": "dev-environment",
"name": "Development",
"values": [
{
"key": "base_url",
"value": "http://localhost:3000",
"type": "default",
"enabled": true
},
{
"key": "auth_url",
"value": "http://localhost:3000",
"type": "default",
"enabled": true
},
{
"key": "client_id",
"value": "dev-client-id",
"type": "secret",
"enabled": true
},
{
"key": "client_secret",
"value": "dev-client-secret",
"type": "secret",
"enabled": true
}
],
"_postman_variable_scope": "environment"
}

View File

@@ -0,0 +1,20 @@
{
"id": "prod-environment",
"name": "Production",
"values": [
{
"key": "base_url",
"value": "https://api.emoney.example.com",
"type": "default",
"enabled": true
},
{
"key": "auth_url",
"value": "https://api.emoney.example.com",
"type": "default",
"enabled": true
}
],
"_postman_variable_scope": "environment"
}

View File

@@ -0,0 +1,20 @@
{
"id": "staging-environment",
"name": "Staging",
"values": [
{
"key": "base_url",
"value": "https://api-staging.emoney.example.com",
"type": "default",
"enabled": true
},
{
"key": "auth_url",
"value": "https://api-staging.emoney.example.com",
"type": "default",
"enabled": true
}
],
"_postman_variable_scope": "environment"
}

View File

@@ -0,0 +1,12 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "LienModes",
"description": "Lien enforcement modes",
"type": "string",
"enum": [
"OFF",
"HARD_FREEZE",
"ENCUMBERED"
]
}

View File

@@ -0,0 +1,13 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Rails",
"description": "Payment rail types",
"type": "string",
"enum": [
"FEDWIRE",
"SWIFT",
"SEPA",
"RTGS"
]
}

View File

@@ -0,0 +1,21 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "ReasonCodes",
"description": "Transfer authorization reason codes",
"type": "string",
"enum": [
"OK",
"PAUSED",
"FROM_FROZEN",
"TO_FROZEN",
"FROM_NOT_COMPLIANT",
"TO_NOT_COMPLIANT",
"LIEN_BLOCK",
"INSUFF_FREE_BAL",
"BRIDGE_ONLY",
"NOT_ALLOWED_ROUTE",
"UNAUTHORIZED",
"CONFIG_ERROR"
]
}

View File

@@ -0,0 +1,17 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "TriggerStates",
"description": "Trigger state machine states",
"type": "string",
"enum": [
"CREATED",
"VALIDATED",
"SUBMITTED_TO_RAIL",
"PENDING",
"SETTLED",
"REJECTED",
"CANCELLED",
"RECALLED"
]
}

View File

@@ -0,0 +1,173 @@
# ISO-20022 Message Type to Canonical Field Mappings
# This file defines how ISO-20022 message types map to canonical message fields
mappings:
# Outbound Initiation Messages
pain.001:
description: "Customer Credit Transfer Initiation"
direction: OUTBOUND
triggerType: OUTBOUND
fields:
instructionId:
path: "Document/CstmrCdtTrfInitn/PmtInf/CdtTrfTxInf/PmtId/InstrId"
type: string
required: true
endToEndId:
path: "Document/CstmrCdtTrfInitn/PmtInf/CdtTrfTxInf/PmtId/EndToEndId"
type: string
required: false
amount:
path: "Document/CstmrCdtTrfInitn/PmtInf/CdtTrfTxInf/Amt/InstdAmt"
type: decimal
required: true
currency:
path: "Document/CstmrCdtTrfInitn/PmtInf/CdtTrfTxInf/Amt/InstdAmt/@Ccy"
type: string
required: true
debtorAccount:
path: "Document/CstmrCdtTrfInitn/PmtInf/DbtrAcct/Id/Othr/Id"
type: string
required: true
creditorAccount:
path: "Document/CstmrCdtTrfInitn/PmtInf/CdtTrfTxInf/CdtrAcct/Id/Othr/Id"
type: string
required: true
pacs.008:
description: "FIToFICustomerCreditTransfer"
direction: OUTBOUND
triggerType: OUTBOUND
fields:
instructionId:
path: "Document/FIToFICstmrCdtTrf/GrpHdr/MsgId"
type: string
required: true
endToEndId:
path: "Document/FIToFICstmrCdtTrf/CdtTrfTxInf/PmtId/EndToEndId"
type: string
required: false
amount:
path: "Document/FIToFICstmrCdtTrf/CdtTrfTxInf/IntrBkSttlmAmt"
type: decimal
required: true
currency:
path: "Document/FIToFICstmrCdtTrf/CdtTrfTxInf/IntrBkSttlmAmt/@Ccy"
type: string
required: true
debtorAccount:
path: "Document/FIToFICstmrCdtTrf/CdtTrfTxInf/DbtrAcct/Id/Othr/Id"
type: string
required: true
creditorAccount:
path: "Document/FIToFICstmrCdtTrf/CdtTrfTxInf/CdtrAcct/Id/Othr/Id"
type: string
required: true
pacs.009:
description: "FinancialInstitutionCreditTransfer"
direction: OUTBOUND
triggerType: OUTBOUND
fields:
instructionId:
path: "Document/FICdtTrf/GrpHdr/MsgId"
type: string
required: true
amount:
path: "Document/FICdtTrf/CdtTrfTxInf/IntrBkSttlmAmt"
type: decimal
required: true
currency:
path: "Document/FICdtTrf/CdtTrfTxInf/IntrBkSttlmAmt/@Ccy"
type: string
required: true
# Inbound Notification Messages
camt.054:
description: "BankToCustomerDebitCreditNotification"
direction: INBOUND
triggerType: INBOUND
fields:
instructionId:
path: "Document/BkToCstmrDbtCdtNtfctn/Ntfctn/Ntry/NtryRef"
type: string
required: true
endToEndId:
path: "Document/BkToCstmrDbtCdtNtfctn/Ntfctn/Ntry/NtryDtls/TxDtls/Refs/EndToEndId"
type: string
required: false
amount:
path: "Document/BkToCstmrDbtCdtNtfctn/Ntfctn/Ntry/Amt"
type: decimal
required: true
currency:
path: "Document/BkToCstmrDbtCdtNtfctn/Ntfctn/Ntry/Amt/@Ccy"
type: string
required: true
account:
path: "Document/BkToCstmrDbtCdtNtfctn/Ntfctn/Acct/Id/Othr/Id"
type: string
required: true
creditDebitIndicator:
path: "Document/BkToCstmrDbtCdtNtfctn/Ntfctn/Ntry/CdtDbtInd"
type: string
required: true
pacs.002:
description: "Payment Status Report"
direction: INBOUND
triggerType: INBOUND
fields:
instructionId:
path: "Document/FIToFIPmtStsRpt/OrgnlGrpInfAndSts/OrgnlMsgId"
type: string
required: true
status:
path: "Document/FIToFIPmtStsRpt/TxInfAndSts/Sts"
type: string
required: true
enum: ["ACSC", "RJCT", "PNDG", "CANC"]
amount:
path: "Document/FIToFIPmtStsRpt/TxInfAndSts/OrgnlTxRef/IntrBkSttlmAmt"
type: decimal
required: false
# Return/Reversal Messages
pacs.004:
description: "Payment Return"
direction: RETURN
triggerType: RETURN
fields:
instructionId:
path: "Document/FIToFIPmtRvsl/OrgnlGrpInf/OrgnlMsgId"
type: string
required: true
originalInstructionId:
path: "Document/FIToFIPmtRvsl/TxInf/OrgnlInstrId"
type: string
required: true
amount:
path: "Document/FIToFIPmtRvsl/TxInf/OrgnlIntrBkSttlmAmt"
type: decimal
required: true
camt.056:
description: "FIToFIPaymentCancellationRequest"
direction: CANCELLATION
triggerType: CANCELLATION
fields:
instructionId:
path: "Document/FIToFIPmtCxlReq/Assgnmt/Id"
type: string
required: true
originalInstructionId:
path: "Document/FIToFIPmtCxlReq/Undrlyg/OrgnlGrpInf/OrgnlMsgId"
type: string
required: true
# Status Code Mappings
statusMappings:
ACSC: SETTLED
RJCT: REJECTED
PNDG: PENDING
CANC: CANCELLED

View File

@@ -0,0 +1,30 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "AccountRef",
"description": "Hashed account reference with provider metadata",
"type": "object",
"required": ["refId"],
"properties": {
"refId": {
"type": "string",
"description": "Hashed account reference identifier",
"pattern": "^0x[a-fA-F0-9]{64}$"
},
"provider": {
"type": "string",
"description": "Account provider identifier",
"enum": ["BANK", "FINTECH", "CUSTODIAN", "OTHER"]
},
"metadata": {
"type": "object",
"description": "Provider-specific metadata (opaque JSON)",
"additionalProperties": true
},
"createdAt": {
"type": "string",
"format": "date-time",
"description": "Account reference creation timestamp"
}
}
}

View File

@@ -0,0 +1,73 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "BridgeLock",
"description": "Bridge lock/unlock event for cross-chain transfers",
"type": "object",
"required": ["lockId", "token", "amount", "status"],
"properties": {
"lockId": {
"type": "string",
"description": "Unique lock identifier",
"pattern": "^[a-fA-F0-9]{64}$"
},
"token": {
"type": "string",
"description": "Token contract address",
"pattern": "^0x[a-fA-F0-9]{40}$"
},
"amount": {
"type": "string",
"description": "Locked amount (wei, as string)",
"pattern": "^[0-9]+$"
},
"from": {
"type": "string",
"description": "Source address (ChainID 138)",
"pattern": "^0x[a-fA-F0-9]{40}$"
},
"targetChain": {
"type": "string",
"description": "Target chain identifier",
"pattern": "^0x[a-fA-F0-9]{64}$"
},
"targetRecipient": {
"type": "string",
"description": "Target chain recipient address",
"pattern": "^0x[a-fA-F0-9]{40}$"
},
"status": {
"type": "string",
"description": "Lock status",
"enum": ["LOCKED", "UNLOCKED", "PENDING"]
},
"sourceChain": {
"type": "string",
"description": "Source chain identifier (for unlocks)",
"pattern": "^0x[a-fA-F0-9]{64}$",
"nullable": true
},
"sourceTx": {
"type": "string",
"description": "Source transaction hash (for unlocks)",
"pattern": "^0x[a-fA-F0-9]{64}$",
"nullable": true
},
"proof": {
"type": "string",
"description": "Light client proof (for unlocks)",
"nullable": true
},
"createdAt": {
"type": "string",
"format": "date-time",
"description": "Lock creation timestamp"
},
"unlockedAt": {
"type": "string",
"format": "date-time",
"description": "Unlock timestamp",
"nullable": true
}
}
}

View File

@@ -0,0 +1,60 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "CanonicalMessage",
"description": "Canonical ISO-20022 message representation",
"type": "object",
"required": ["msgType", "instructionId", "payloadHash"],
"properties": {
"msgType": {
"type": "string",
"description": "ISO-20022 message type (e.g., pacs.008, pain.001)",
"pattern": "^[a-z]+\\.[0-9]{3}$"
},
"instructionId": {
"type": "string",
"description": "Unique instruction identifier",
"pattern": "^[a-fA-F0-9]{64}$"
},
"endToEndId": {
"type": "string",
"description": "End-to-end reference (optional)",
"pattern": "^[a-fA-F0-9]{64}$"
},
"accountRefId": {
"type": "string",
"description": "Hashed account reference",
"pattern": "^0x[a-fA-F0-9]{64}$"
},
"counterpartyRefId": {
"type": "string",
"description": "Hashed counterparty reference",
"pattern": "^0x[a-fA-F0-9]{64}$"
},
"token": {
"type": "string",
"description": "Token contract address",
"pattern": "^0x[a-fA-F0-9]{40}$"
},
"amount": {
"type": "string",
"description": "Transfer amount (wei, as string)",
"pattern": "^[0-9]+$"
},
"currencyCode": {
"type": "string",
"description": "Currency code hash",
"pattern": "^0x[a-fA-F0-9]{64}$"
},
"payloadHash": {
"type": "string",
"description": "Hash of full ISO-20022 XML payload",
"pattern": "^0x[a-fA-F0-9]{64}$"
},
"createdAt": {
"type": "string",
"format": "date-time",
"description": "Message creation timestamp"
}
}
}

View File

@@ -0,0 +1,39 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "ComplianceProfile",
"description": "Compliance status for an account or wallet",
"type": "object",
"required": ["refId", "allowed", "frozen"],
"properties": {
"refId": {
"type": "string",
"description": "Hashed account or wallet reference identifier",
"pattern": "^0x[a-fA-F0-9]{64}$"
},
"allowed": {
"type": "boolean",
"description": "Whether the account is allowed (compliant)"
},
"frozen": {
"type": "boolean",
"description": "Whether the account is frozen"
},
"riskTier": {
"type": "integer",
"description": "Risk tier (0-255)",
"minimum": 0,
"maximum": 255
},
"jurisdictionHash": {
"type": "string",
"description": "Hash of jurisdiction information",
"pattern": "^0x[a-fA-F0-9]{64}$"
},
"updatedAt": {
"type": "string",
"format": "date-time",
"description": "Last update timestamp"
}
}
}

View File

@@ -0,0 +1,58 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Lien",
"description": "Lien (encumbrance) on an account for debt/liability enforcement",
"type": "object",
"required": ["lienId", "debtor", "amount", "active"],
"properties": {
"lienId": {
"type": "string",
"description": "Unique lien identifier",
"pattern": "^[0-9]+$"
},
"debtor": {
"type": "string",
"description": "Debtor account address or hashed account reference",
"pattern": "^(0x[a-fA-F0-9]{40}|0x[a-fA-F0-9]{64})$"
},
"amount": {
"type": "string",
"description": "Lien amount (wei, as string to handle large numbers)",
"pattern": "^[0-9]+$"
},
"expiry": {
"type": "integer",
"description": "Expiry timestamp (Unix epoch seconds). 0 means no expiry.",
"minimum": 0
},
"priority": {
"type": "integer",
"description": "Lien priority (0-255)",
"minimum": 0,
"maximum": 255
},
"authority": {
"type": "string",
"description": "Address of the authority that placed the lien",
"pattern": "^0x[a-fA-F0-9]{40}$"
},
"reasonCode": {
"$ref": "../enums/ReasonCodes.json"
},
"active": {
"type": "boolean",
"description": "Whether the lien is currently active"
},
"createdAt": {
"type": "string",
"format": "date-time",
"description": "Lien creation timestamp"
},
"updatedAt": {
"type": "string",
"format": "date-time",
"description": "Last update timestamp"
}
}
}

View File

@@ -0,0 +1,76 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Packet",
"description": "Non-scheme integration packet (PDF/AS4/Secure email)",
"type": "object",
"required": ["packetId", "payloadHash", "channel", "status"],
"properties": {
"packetId": {
"type": "string",
"description": "Unique packet identifier",
"pattern": "^[a-fA-F0-9]{64}$"
},
"triggerId": {
"type": "string",
"description": "Associated trigger identifier",
"pattern": "^[a-fA-F0-9]{64}$"
},
"instructionId": {
"type": "string",
"description": "Instruction identifier",
"pattern": "^[a-fA-F0-9]{64}$"
},
"payloadHash": {
"type": "string",
"description": "Hash of packet payload",
"pattern": "^0x[a-fA-F0-9]{64}$"
},
"channel": {
"type": "string",
"description": "Packet delivery channel",
"enum": ["PDF", "AS4", "EMAIL", "PORTAL"]
},
"messageRef": {
"type": "string",
"description": "Message reference for tracking",
"nullable": true
},
"status": {
"type": "string",
"description": "Packet status",
"enum": ["GENERATED", "DISPATCHED", "DELIVERED", "ACKNOWLEDGED", "FAILED"]
},
"acknowledgements": {
"type": "array",
"items": {
"type": "object",
"properties": {
"ackId": {
"type": "string"
},
"receivedAt": {
"type": "string",
"format": "date-time"
},
"status": {
"type": "string",
"enum": ["RECEIVED", "ACCEPTED", "REJECTED"]
}
}
},
"description": "Acknowledgement records"
},
"createdAt": {
"type": "string",
"format": "date-time",
"description": "Packet creation timestamp"
},
"dispatchedAt": {
"type": "string",
"format": "date-time",
"description": "Packet dispatch timestamp",
"nullable": true
}
}
}

View File

@@ -0,0 +1,87 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Token",
"description": "eMoney token metadata and configuration",
"type": "object",
"required": ["code", "address", "name", "symbol", "decimals", "issuer"],
"properties": {
"code": {
"type": "string",
"description": "Token code (e.g., USDW)",
"pattern": "^[A-Z0-9]{1,10}$"
},
"address": {
"type": "string",
"description": "Token contract address on ChainID 138",
"pattern": "^0x[a-fA-F0-9]{40}$"
},
"name": {
"type": "string",
"description": "Token name",
"minLength": 1,
"maxLength": 100
},
"symbol": {
"type": "string",
"description": "Token symbol",
"minLength": 1,
"maxLength": 10
},
"decimals": {
"type": "integer",
"description": "Number of decimals (typically 18)",
"minimum": 0,
"maximum": 255
},
"issuer": {
"type": "string",
"description": "Issuer address",
"pattern": "^0x[a-fA-F0-9]{40}$"
},
"policy": {
"$ref": "#/definitions/TokenPolicy"
},
"createdAt": {
"type": "string",
"format": "date-time",
"description": "Token deployment timestamp"
}
},
"definitions": {
"TokenPolicy": {
"type": "object",
"properties": {
"paused": {
"type": "boolean",
"description": "Whether the token is paused"
},
"bridgeOnly": {
"type": "boolean",
"description": "Whether token only allows transfers to/from bridge"
},
"bridge": {
"type": "string",
"description": "Bridge contract address",
"pattern": "^0x[a-fA-F0-9]{40}$"
},
"lienMode": {
"type": "string",
"enum": ["OFF", "HARD_FREEZE", "ENCUMBERED"],
"description": "Lien enforcement mode"
},
"forceTransferMode": {
"type": "boolean",
"description": "Whether force transfers are enabled"
},
"routes": {
"type": "array",
"items": {
"$ref": "../enums/Rails.json"
},
"description": "Allowed payment rails"
}
}
}
}
}

View File

@@ -0,0 +1,79 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Trigger",
"description": "Payment rail trigger with state machine",
"type": "object",
"required": ["triggerId", "rail", "msgType", "state", "instructionId"],
"properties": {
"triggerId": {
"type": "string",
"description": "Unique trigger identifier",
"pattern": "^[a-fA-F0-9]{64}$"
},
"rail": {
"$ref": "../enums/Rails.json"
},
"msgType": {
"type": "string",
"description": "ISO-20022 message type (e.g., pacs.008, pain.001)",
"pattern": "^[a-z]+\\.[0-9]{3}$"
},
"state": {
"$ref": "../enums/TriggerStates.json"
},
"instructionId": {
"type": "string",
"description": "Unique instruction identifier for idempotency",
"pattern": "^[a-fA-F0-9]{64}$"
},
"endToEndId": {
"type": "string",
"description": "End-to-end reference (optional)",
"pattern": "^[a-fA-F0-9]{64}$"
},
"canonicalMessage": {
"$ref": "CanonicalMessage.json"
},
"payloadHash": {
"type": "string",
"description": "Hash of full ISO-20022 XML payload",
"pattern": "^0x[a-fA-F0-9]{64}$"
},
"amount": {
"type": "string",
"description": "Transfer amount (wei, as string)",
"pattern": "^[0-9]+$"
},
"token": {
"type": "string",
"description": "Token contract address",
"pattern": "^0x[a-fA-F0-9]{40}$"
},
"accountRefId": {
"type": "string",
"description": "Hashed account reference",
"pattern": "^0x[a-fA-F0-9]{64}$"
},
"counterpartyRefId": {
"type": "string",
"description": "Hashed counterparty reference",
"pattern": "^0x[a-fA-F0-9]{64}$"
},
"railTxRef": {
"type": "string",
"description": "Rail transaction reference (set after submission)",
"nullable": true
},
"createdAt": {
"type": "string",
"format": "date-time",
"description": "Trigger creation timestamp"
},
"updatedAt": {
"type": "string",
"format": "date-time",
"description": "Last state update timestamp"
}
}
}

View File

@@ -0,0 +1,35 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "WalletRef",
"description": "Hashed wallet reference with provider metadata",
"type": "object",
"required": ["refId"],
"properties": {
"refId": {
"type": "string",
"description": "Hashed wallet reference identifier",
"pattern": "^0x[a-fA-F0-9]{64}$"
},
"provider": {
"type": "string",
"description": "Wallet provider identifier",
"enum": ["WALLETCONNECT", "FIREBLOCKS", "METAMASK", "OTHER"]
},
"address": {
"type": "string",
"description": "Wallet address on ChainID 138",
"pattern": "^0x[a-fA-F0-9]{40}$"
},
"metadata": {
"type": "object",
"description": "Provider-specific metadata (opaque JSON)",
"additionalProperties": true
},
"createdAt": {
"type": "string",
"format": "date-time",
"description": "Wallet reference creation timestamp"
}
}
}

View File

@@ -0,0 +1,24 @@
{
"name": "@emoney/schemas",
"version": "1.0.0",
"description": "Canonical JSON Schema registry for eMoney Token Factory API",
"main": "index.js",
"types": "index.d.ts",
"scripts": {
"validate": "node scripts/validate-schemas.js",
"generate-types": "node scripts/generate-types.js"
},
"keywords": [
"json-schema",
"emoney",
"api"
],
"author": "",
"license": "MIT",
"devDependencies": {
"ajv": "^8.12.0",
"ajv-formats": "^2.1.1",
"typescript": "^5.3.0"
}
}