v0.5.1-pre.008
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
# file: Cargo.toml
|
# file: Cargo.toml
|
||||||
# version: 51
|
# version: 52
|
||||||
|
|
||||||
[workspace]
|
[workspace]
|
||||||
resolver = "3"
|
resolver = "3"
|
||||||
@@ -18,7 +18,7 @@ members = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
version = "0.5.1-pre.7"
|
version = "0.5.1-pre.8"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
repository = "https://git.sasedev.com/Sasedev/khadhroony-bot3"
|
repository = "https://git.sasedev.com/Sasedev/khadhroony-bot3"
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<!-- file: README.md -->
|
<!-- file: README.md -->
|
||||||
<!-- version: 22 -->
|
<!-- version: 23 -->
|
||||||
|
|
||||||
# Khadhroony Bot3
|
# Khadhroony Bot3
|
||||||
|
|
||||||
@@ -23,6 +23,8 @@ Le workspace contient onze crates :
|
|||||||
|
|
||||||
La série `0.5.x` prépare la séparation explicite entre le domaine applicatif `khadhroony-bot` et les bibliothèques généralistes `khadhroony-solana`. Depuis `0.5.1-pre.002`, les dix crates généralistes utilisent les noms `ks-*` / `ks_*`, tandis que `kb-app-demo-desktop` conserve son nom et reste une application du workspace Bot. Le workspace, le dépôt et le répertoire racine restent nommés `khadhroony-bot3` pendant cette migration et ne doivent pas être renommés avant `1.0` ou une version ultérieure explicitement dédiée. La politique de migration est définie dans [`docs/decisions/KHADHROONY_SOLANA_NAMESPACE_POLICY.md`](docs/decisions/KHADHROONY_SOLANA_NAMESPACE_POLICY.md).
|
La série `0.5.x` prépare la séparation explicite entre le domaine applicatif `khadhroony-bot` et les bibliothèques généralistes `khadhroony-solana`. Depuis `0.5.1-pre.002`, les dix crates généralistes utilisent les noms `ks-*` / `ks_*`, tandis que `kb-app-demo-desktop` conserve son nom et reste une application du workspace Bot. Le workspace, le dépôt et le répertoire racine restent nommés `khadhroony-bot3` pendant cette migration et ne doivent pas être renommés avant `1.0` ou une version ultérieure explicitement dédiée. La politique de migration est définie dans [`docs/decisions/KHADHROONY_SOLANA_NAMESPACE_POLICY.md`](docs/decisions/KHADHROONY_SOLANA_NAMESPACE_POLICY.md).
|
||||||
|
|
||||||
|
Depuis `0.5.1-pre.008`, les contrats de configuration source/runtime susceptibles de contenir des secrets restent backend-only et ne sont ni sérialisables ni `Debug` par défaut. Les crates `ks-config` et `ks-lib` ne génèrent plus de bindings TS-RS ; les surfaces TypeScript/Tauri sont possédées par les applications via des DTO explicites.
|
||||||
|
|
||||||
Références :
|
Références :
|
||||||
|
|
||||||
- [`docs/architecture/ARCHITECTURE.md`](docs/architecture/ARCHITECTURE.md) ;
|
- [`docs/architecture/ARCHITECTURE.md`](docs/architecture/ARCHITECTURE.md) ;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<!-- file: config/README.md -->
|
<!-- file: config/README.md -->
|
||||||
<!-- version: 22 -->
|
<!-- version: 24 -->
|
||||||
|
|
||||||
# Configuration locale
|
# Configuration locale
|
||||||
|
|
||||||
@@ -36,15 +36,17 @@ config/
|
|||||||
├── store.config.json
|
├── store.config.json
|
||||||
├── wallet.config.json
|
├── wallet.config.json
|
||||||
├── execution.config.json
|
├── execution.config.json
|
||||||
├── example.kb-app-demo-desktop.default.config.json
|
├── exemples/
|
||||||
├── example.logging.config.json
|
│ ├── example.kb-app-demo-desktop.default.config.json
|
||||||
├── example.transport.config.json
|
│ ├── example.logging.config.json
|
||||||
├── example.listeners.config.json
|
│ ├── example.transport.config.json
|
||||||
├── example.store.config.json
|
│ ├── example.listeners.config.json
|
||||||
├── example.wallet.config.json
|
│ ├── example.store.config.json
|
||||||
├── example.execution.config.json
|
│ ├── example.wallet.config.json
|
||||||
|
│ └── example.execution.config.json
|
||||||
└── schemas/
|
└── schemas/
|
||||||
├── composition.config.schema.json
|
├── composition.config.schema.json
|
||||||
|
├── kb-app-demo-desktop.application.config.schema.json
|
||||||
├── logging.config.schema.json
|
├── logging.config.schema.json
|
||||||
├── transport.config.schema.json
|
├── transport.config.schema.json
|
||||||
├── listeners.config.schema.json
|
├── listeners.config.schema.json
|
||||||
@@ -54,7 +56,7 @@ config/
|
|||||||
└── resolved.app.config.schema.json
|
└── resolved.app.config.schema.json
|
||||||
```
|
```
|
||||||
|
|
||||||
`resolved.app.config.schema.json` décrit uniquement le contrat transitoire `AppConfig/ProfileConfig` reconstruit en mémoire. Aucun binaire ne charge ce schéma comme document source applicatif.
|
`resolved.app.config.schema.json` décrit uniquement le contrat transitoire `AppConfig/ProfileConfig` reconstruit en mémoire. Aucun binaire ne charge ce schéma comme document source applicatif. La section `application` d'une composition reste opaque pour `ks-config`; `kb-app-demo-desktop` la valide avec `config/schemas/kb-app-demo-desktop.application.config.schema.json`.
|
||||||
|
|
||||||
## Defaults et overrides
|
## Defaults et overrides
|
||||||
|
|
||||||
@@ -110,14 +112,20 @@ Les defaults portent les timeouts, capacités de channels et `auto_reconnect`. U
|
|||||||
|
|
||||||
`store.config.json` possède la sélection et les paramètres PostgreSQL/SQLite. Le split reste structurel : aucune migration SQL n'est introduite par `0.5.1`.
|
`store.config.json` possède la sélection et les paramètres PostgreSQL/SQLite. Le split reste structurel : aucune migration SQL n'est introduite par `0.5.1`.
|
||||||
|
|
||||||
|
## Frontière source/runtime/public/diagnostic
|
||||||
|
|
||||||
|
Les documents source et le contrat runtime résolu peuvent contenir des valeurs sensibles après résolution des placeholders. Ils restent backend-only et ne sont ni sérialisables ni `Debug` par défaut. Les applications construisent explicitement leurs DTO publics et diagnostics bornés, sans sérialiser puis masquer un `AppConfig/ProfileConfig` complet.
|
||||||
|
|
||||||
|
Une valeur composée hérite de la sensibilité la plus forte de ses placeholders (`Secret > Internal > Public`). Une URL ou un DSN incorporant un `KS_SECRET_*`/`KB_SECRET_*` est donc secret même si le champ final ne porte pas le mot `SECRET`.
|
||||||
|
|
||||||
## Variables d'environnement
|
## Variables d'environnement
|
||||||
|
|
||||||
Les composants `ks-*` utilisent `KS_SECRET_*`, `KS_PUBLIC_*` ou `KS_*`. Les besoins réellement spécifiques à une application `kb-*` utilisent `KB_SECRET_*`, `KB_PUBLIC_*` ou `KB_*`.
|
Les composants `ks-*` utilisent `KS_SECRET_*`, `KS_PUBLIC_*` ou `KS_*`. Les besoins réellement spécifiques à une application `kb-*` utilisent `KB_SECRET_*`, `KB_PUBLIC_*` ou `KB_*`.
|
||||||
|
|
||||||
Les secrets ne sont jamais écrits en clair dans le dépôt. La séparation source/runtime/public/diagnostic et le camouflage systématique sont traités après ce split.
|
Les secrets ne sont jamais écrits en clair dans le dépôt. Depuis `0.5.1-pre.008`, les contrats source/runtime sensibles restent backend-only, tandis que les applications exposent uniquement des DTO publics ou diagnostics explicitement bornés.
|
||||||
|
|
||||||
## Exemples et schémas
|
## Exemples et schémas
|
||||||
|
|
||||||
Les exemples sous `config/` sont des références conformes et ne sont pas chargés automatiquement. Tous les schémas actifs résident exclusivement sous `config/schemas/`.
|
Les exemples sous `config/exemples/` sont des références conformes et ne sont pas chargés automatiquement. Tous les schémas actifs résident exclusivement sous `config/schemas/`.
|
||||||
|
|
||||||
Les fichiers historiques `app.config.json`, `example.app.config.json`, `schemas/app.config.schema.json`, `example.config.json`, `schema.config.json` et `ks-pipeline-demo-scenarios.default.config.json` sont obsolètes dans l'architecture courante.
|
Les fichiers historiques `app.config.json`, `example.app.config.json`, `schemas/app.config.schema.json`, `example.config.json`, `schema.config.json` et `ks-pipeline-demo-scenarios.default.config.json` sont obsolètes dans l'architecture courante.
|
||||||
|
|||||||
@@ -11,13 +11,13 @@
|
|||||||
"profiles": [
|
"profiles": [
|
||||||
{
|
{
|
||||||
"name": "local_devnet",
|
"name": "local_devnet",
|
||||||
"app": {
|
"application": {
|
||||||
"name": "khadhroony-bot3",
|
"name": "khadhroony-bot3",
|
||||||
"environment": "development"
|
"environment": "development",
|
||||||
},
|
"demo": {
|
||||||
"demo": {
|
"live_demo_enabled": true,
|
||||||
"live_demo_enabled": true,
|
"trading_demo_enabled": false
|
||||||
"trading_demo_enabled": false
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -11,24 +11,24 @@
|
|||||||
"profiles": [
|
"profiles": [
|
||||||
{
|
{
|
||||||
"name": "local_devnet",
|
"name": "local_devnet",
|
||||||
"app": {
|
"application": {
|
||||||
"name": "khadhroony-bot3",
|
"name": "khadhroony-bot3",
|
||||||
"environment": "development"
|
"environment": "development",
|
||||||
},
|
"demo": {
|
||||||
"demo": {
|
"live_demo_enabled": true,
|
||||||
"live_demo_enabled": true,
|
"trading_demo_enabled": false
|
||||||
"trading_demo_enabled": false
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "mainnet_research",
|
"name": "mainnet_research",
|
||||||
"app": {
|
"application": {
|
||||||
"name": "khadhroony-bot3",
|
"name": "khadhroony-bot3",
|
||||||
"environment": "research"
|
"environment": "research",
|
||||||
},
|
"demo": {
|
||||||
"demo": {
|
"live_demo_enabled": true,
|
||||||
"live_demo_enabled": true,
|
"trading_demo_enabled": false
|
||||||
"trading_demo_enabled": false
|
}
|
||||||
},
|
},
|
||||||
"logging_profile": "mainnet_research",
|
"logging_profile": "mainnet_research",
|
||||||
"transport_profile": "mainnet_research",
|
"transport_profile": "mainnet_research",
|
||||||
@@ -39,13 +39,13 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "mainnet",
|
"name": "mainnet",
|
||||||
"app": {
|
"application": {
|
||||||
"name": "khadhroony-bot3",
|
"name": "khadhroony-bot3",
|
||||||
"environment": "mainnet"
|
"environment": "mainnet",
|
||||||
},
|
"demo": {
|
||||||
"demo": {
|
"live_demo_enabled": true,
|
||||||
"live_demo_enabled": true,
|
"trading_demo_enabled": false
|
||||||
"trading_demo_enabled": false
|
}
|
||||||
},
|
},
|
||||||
"logging_profile": "mainnet",
|
"logging_profile": "mainnet",
|
||||||
"transport_profile": "mainnet",
|
"transport_profile": "mainnet",
|
||||||
|
|||||||
@@ -29,38 +29,6 @@
|
|||||||
"type": "string",
|
"type": "string",
|
||||||
"minLength": 1
|
"minLength": 1
|
||||||
},
|
},
|
||||||
"app_section": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": false,
|
|
||||||
"required": [
|
|
||||||
"name",
|
|
||||||
"environment"
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"name": {
|
|
||||||
"$ref": "#/$defs/non_empty_string"
|
|
||||||
},
|
|
||||||
"environment": {
|
|
||||||
"$ref": "#/$defs/non_empty_string"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"demo": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": false,
|
|
||||||
"required": [
|
|
||||||
"live_demo_enabled",
|
|
||||||
"trading_demo_enabled"
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"live_demo_enabled": {
|
|
||||||
"type": "boolean"
|
|
||||||
},
|
|
||||||
"trading_demo_enabled": {
|
|
||||||
"type": "boolean"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"sources": {
|
"sources": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
@@ -97,19 +65,14 @@
|
|||||||
"type": "object",
|
"type": "object",
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"required": [
|
"required": [
|
||||||
"name",
|
"name"
|
||||||
"app",
|
|
||||||
"demo"
|
|
||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"name": {
|
"name": {
|
||||||
"$ref": "#/$defs/non_empty_string"
|
"$ref": "#/$defs/non_empty_string"
|
||||||
},
|
},
|
||||||
"app": {
|
"application": {
|
||||||
"$ref": "#/$defs/app_section"
|
"type": "object"
|
||||||
},
|
|
||||||
"demo": {
|
|
||||||
"$ref": "#/$defs/demo"
|
|
||||||
},
|
},
|
||||||
"logging_profile": {
|
"logging_profile": {
|
||||||
"$ref": "#/$defs/non_empty_string"
|
"$ref": "#/$defs/non_empty_string"
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||||
|
"$id": "https://khadhroony.local/schemas/kb-app-demo-desktop.application.config.schema.json",
|
||||||
|
"title": "Khadhroony Bot desktop application composition fragment",
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"name",
|
||||||
|
"environment",
|
||||||
|
"demo"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 1
|
||||||
|
},
|
||||||
|
"environment": {
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 1
|
||||||
|
},
|
||||||
|
"demo": {
|
||||||
|
"$ref": "#/$defs/demo"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"$defs": {
|
||||||
|
"demo": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"live_demo_enabled",
|
||||||
|
"trading_demo_enabled"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"live_demo_enabled": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"trading_demo_enabled": {
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -30,20 +30,15 @@
|
|||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"required": [
|
"required": [
|
||||||
"name",
|
"name",
|
||||||
"app",
|
|
||||||
"database",
|
"database",
|
||||||
"solana",
|
"solana",
|
||||||
"wallet",
|
"wallet",
|
||||||
"execution",
|
"execution"
|
||||||
"demo"
|
|
||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"name": {
|
"name": {
|
||||||
"$ref": "#/$defs/non_empty_string"
|
"$ref": "#/$defs/non_empty_string"
|
||||||
},
|
},
|
||||||
"app": {
|
|
||||||
"$ref": "#/$defs/app_section"
|
|
||||||
},
|
|
||||||
"database": {
|
"database": {
|
||||||
"$ref": "#/$defs/database"
|
"$ref": "#/$defs/database"
|
||||||
},
|
},
|
||||||
@@ -55,25 +50,6 @@
|
|||||||
},
|
},
|
||||||
"execution": {
|
"execution": {
|
||||||
"$ref": "#/$defs/execution"
|
"$ref": "#/$defs/execution"
|
||||||
},
|
|
||||||
"demo": {
|
|
||||||
"$ref": "#/$defs/demo"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"app_section": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": false,
|
|
||||||
"required": [
|
|
||||||
"name",
|
|
||||||
"environment"
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"name": {
|
|
||||||
"$ref": "#/$defs/non_empty_string"
|
|
||||||
},
|
|
||||||
"environment": {
|
|
||||||
"$ref": "#/$defs/non_empty_string"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -608,22 +584,6 @@
|
|||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"demo": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": false,
|
|
||||||
"required": [
|
|
||||||
"live_demo_enabled",
|
|
||||||
"trading_demo_enabled"
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"live_demo_enabled": {
|
|
||||||
"type": "boolean"
|
|
||||||
},
|
|
||||||
"trading_demo_enabled": {
|
|
||||||
"type": "boolean"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -559,7 +559,7 @@ Dans **Décodeur spl_token — TransferChecked** :
|
|||||||
| Compte source | `$KS_DEVNET_CLASSIC_SOURCE_ATA` |
|
| Compte source | `$KS_DEVNET_CLASSIC_SOURCE_ATA` |
|
||||||
| Mint | `$KS_DEVNET_CLASSIC_MINT` |
|
| Mint | `$KS_DEVNET_CLASSIC_MINT` |
|
||||||
| Compte destination | `$KS_DEVNET_CLASSIC_DESTINATION_ATA` |
|
| Compte destination | `$KS_DEVNET_CLASSIC_DESTINATION_ATA` |
|
||||||
| Autorité simple | `$KS_PUBLIC_DEVNET_WALLET_ADDRESS` |
|
| Autorité simple | `$KS_PUBLIC_DEVNET_WALLET_ADDRESS` |
|
||||||
| Montant brut exact | `1000000000` pour 1 token avec 9 décimales |
|
| Montant brut exact | `1000000000` pour 1 token avec 9 décimales |
|
||||||
| Decimals | `9` |
|
| Decimals | `9` |
|
||||||
|
|
||||||
|
|||||||
@@ -5,19 +5,19 @@
|
|||||||
|
|
||||||
## 1. Inventaire
|
## 1. Inventaire
|
||||||
|
|
||||||
| Crate | Type | Responsabilité principale | État documentaire |
|
| Crate | Type | Responsabilité principale | État documentaire |
|
||||||
|------------------------------|------------------------|--------------------------------------------------------------------|------------------------------------------|
|
|------------------------------|------------------------|--------------------------------------------------------------------------------------|------------------------------------------|
|
||||||
| `ks-core` | bibliothèque | erreurs, résultat et identité de module partagés | README/TODO/USAGE/CHANGELOG présents |
|
| `ks-core` | bibliothèque | erreurs, résultat et identité de module partagés | README/TODO/USAGE/CHANGELOG présents |
|
||||||
| `ks-config` | bibliothèque | compositions binaires, documents JSON partagés, environnement, validation et profils | migration/restructuration en `0.5.1` |
|
| `ks-config` | bibliothèque | compositions binaires, documents JSON partagés, environnement, validation et profils | migration/restructuration en `0.5.1` |
|
||||||
| `ks-lib` | bibliothèque | modèles, décodeurs, exécuteurs et matérialisateurs consolidés | README/TODO/USAGE/CHANGELOG présents |
|
| `ks-lib` | bibliothèque | modèles, décodeurs, exécuteurs et matérialisateurs consolidés | README/TODO/USAGE/CHANGELOG présents |
|
||||||
| `ks-logging` | bibliothèque | initialisation du logging et du tracing | README/TODO/USAGE/CHANGELOG présents |
|
| `ks-logging` | bibliothèque | initialisation du logging et du tracing | README/TODO/USAGE/CHANGELOG présents |
|
||||||
| `ks-program-ids` | bibliothèque | registre des programmes et comptes Solana connus | README/TODO/USAGE/CHANGELOG présents |
|
| `ks-program-ids` | bibliothèque | registre des programmes et comptes Solana connus | README/TODO/USAGE/CHANGELOG présents |
|
||||||
| `ks-pipeline` | bibliothèque | backfill, extraction, replay, stateful, préflight et orchestration | README/TODO/USAGE/CHANGELOG présents |
|
| `ks-pipeline` | bibliothèque | backfill, extraction, replay, stateful, préflight et orchestration | README/TODO/USAGE/CHANGELOG présents |
|
||||||
| `ks-pipeline-demo-scenarios` | bibliothèque + binaire | scénarios Devnet réutilisables et CLI | nom `ks-*` actif ; audit `0.5.4` |
|
| `ks-pipeline-demo-scenarios` | bibliothèque + binaire | scénarios Devnet réutilisables et CLI | nom `ks-*` actif ; audit `0.5.4` |
|
||||||
| `ks-onchain-transport` | bibliothèque | transports RPC HTTP/WebSocket et pools d’endpoints | README/TODO/USAGE/CHANGELOG présents |
|
| `ks-onchain-transport` | bibliothèque | transports RPC HTTP/WebSocket et pools d’endpoints | README/TODO/USAGE/CHANGELOG présents |
|
||||||
| `ks-store` | bibliothèque | contrats de stockage et adaptateur PostgreSQL | nom `ks-*` actif ; normalisation `0.5.3` |
|
| `ks-store` | bibliothèque | contrats de stockage et adaptateur PostgreSQL | nom `ks-*` actif ; normalisation `0.5.3` |
|
||||||
| `ks-wallet` | bibliothèque | wallet temporaire et frontière de signataire | nom `ks-*` actif ; refonte `0.5.2` |
|
| `ks-wallet` | bibliothèque | wallet temporaire et frontière de signataire | nom `ks-*` actif ; refonte `0.5.2` |
|
||||||
| `kb-app-demo-desktop` | bibliothèque + binaire | application de démonstration Tauri | documentée ; réconciliation en `0.5.4` |
|
| `kb-app-demo-desktop` | bibliothèque + binaire | application de démonstration Tauri | documentée ; réconciliation en `0.5.4` |
|
||||||
|
|
||||||
La table décrit les noms physiques actifs depuis `0.5.1-pre.002`. La migration a renommé les dix crates généralistes en `ks-core`, `ks-config`, `ks-lib`, `ks-logging`, `ks-program-ids`, `ks-pipeline`, `ks-pipeline-demo-scenarios`, `ks-onchain-transport`, `ks-store` et `ks-wallet`. `kb-app-demo-desktop` conserve son nom parce qu’il appartient au domaine applicatif Bot. Voir [`../decisions/KHADHROONY_SOLANA_NAMESPACE_POLICY.md`](../decisions/KHADHROONY_SOLANA_NAMESPACE_POLICY.md).
|
La table décrit les noms physiques actifs depuis `0.5.1-pre.002`. La migration a renommé les dix crates généralistes en `ks-core`, `ks-config`, `ks-lib`, `ks-logging`, `ks-program-ids`, `ks-pipeline`, `ks-pipeline-demo-scenarios`, `ks-onchain-transport`, `ks-store` et `ks-wallet`. `kb-app-demo-desktop` conserve son nom parce qu’il appartient au domaine applicatif Bot. Voir [`../decisions/KHADHROONY_SOLANA_NAMESPACE_POLICY.md`](../decisions/KHADHROONY_SOLANA_NAMESPACE_POLICY.md).
|
||||||
|
|
||||||
|
|||||||
@@ -25,18 +25,18 @@ Le renommage des bibliothèques internes ne renomme pas le workspace, le dépôt
|
|||||||
|
|
||||||
La migration `0.5.1-pre.002` renomme les dix crates généralistes suivantes :
|
La migration `0.5.1-pre.002` renomme les dix crates généralistes suivantes :
|
||||||
|
|
||||||
| Nom `0.5.0` | Nom cible |
|
| Nom `0.5.0` | Nom cible |
|
||||||
|---|---|
|
|------------------------------|------------------------------|
|
||||||
| `kb-core` | `ks-core` |
|
| `kb-core` | `ks-core` |
|
||||||
| `kb-config` | `ks-config` |
|
| `kb-config` | `ks-config` |
|
||||||
| `kb-lib` | `ks-lib` |
|
| `kb-lib` | `ks-lib` |
|
||||||
| `kb-logging` | `ks-logging` |
|
| `kb-logging` | `ks-logging` |
|
||||||
| `kb-program-ids` | `ks-program-ids` |
|
| `kb-program-ids` | `ks-program-ids` |
|
||||||
| `kb-pipeline` | `ks-pipeline` |
|
| `kb-pipeline` | `ks-pipeline` |
|
||||||
| `kb-pipeline-demo-scenarios` | `ks-pipeline-demo-scenarios` |
|
| `kb-pipeline-demo-scenarios` | `ks-pipeline-demo-scenarios` |
|
||||||
| `kb-onchain-transport` | `ks-onchain-transport` |
|
| `kb-onchain-transport` | `ks-onchain-transport` |
|
||||||
| `kb-store` | `ks-store` |
|
| `kb-store` | `ks-store` |
|
||||||
| `kb-wallet` | `ks-wallet` |
|
| `kb-wallet` | `ks-wallet` |
|
||||||
|
|
||||||
Les identifiants Rust correspondants migrent dans le même delta vers `ks_*` : par exemple `kb_config` devient `ks_config` et `kb_pipeline_demo_scenarios` devient `ks_pipeline_demo_scenarios`.
|
Les identifiants Rust correspondants migrent dans le même delta vers `ks_*` : par exemple `kb_config` devient `ks_config` et `kb_pipeline_demo_scenarios` devient `ks_pipeline_demo_scenarios`.
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<!-- file: docs/guides/CONFIGURATION.md -->
|
<!-- file: docs/guides/CONFIGURATION.md -->
|
||||||
<!-- version: 7 -->
|
<!-- version: 9 -->
|
||||||
|
|
||||||
# Guide de configuration
|
# Guide de configuration
|
||||||
|
|
||||||
@@ -22,7 +22,7 @@ Documents partagés :
|
|||||||
- `config/wallet.config.json` ;
|
- `config/wallet.config.json` ;
|
||||||
- `config/execution.config.json`.
|
- `config/execution.config.json`.
|
||||||
|
|
||||||
Chaque document possède un exemple `example.*.config.json`. Les schémas correspondants résident sous `config/schemas/`.
|
Chaque document possède un exemple sous `config/exemples/` avec un nom `example.*.config.json`. Les schémas correspondants résident sous `config/schemas/`.
|
||||||
|
|
||||||
`.env`, ou le fichier sélectionné par `KS_ENV_FILE`, fournit les valeurs non versionnées.
|
`.env`, ou le fichier sélectionné par `KS_ENV_FILE`, fournit les valeurs non versionnées.
|
||||||
|
|
||||||
@@ -145,22 +145,29 @@ appartiennent à `execution.config.json`, avec les limites de dépense, frais, s
|
|||||||
|
|
||||||
## Contrat runtime transitoire
|
## Contrat runtime transitoire
|
||||||
|
|
||||||
Pendant `0.5.1`, `ks-config` reconstruit encore `AppConfig/ProfileConfig` afin de préserver les consommateurs existants. Il s'agit d'une projection runtime, pas d'un document source.
|
Pendant `0.5.1`, `ks-config` reconstruit encore `AppConfig/ProfileConfig` afin de préserver les consommateurs backend existants. Il s'agit d'une projection runtime, pas d'un document source ni d'une surface de sortie. Depuis `pre.008`, ces contrats et les documents spécialisés susceptibles de contenir des valeurs résolues ne dérivent ni `serde::Serialize` ni `Debug`.
|
||||||
|
|
||||||
Les fixtures de compatibilité sont sous `test-fixtures/config/`. Elles ne doivent pas être chargées en production.
|
Les fixtures de compatibilité sont sous `test-fixtures/config/`. Elles ne doivent pas être chargées en production.
|
||||||
|
|
||||||
|
## Frontière publique et diagnostic
|
||||||
|
|
||||||
|
Une application ne transmet jamais `AppConfig/ProfileConfig` directement. Elle construit :
|
||||||
|
|
||||||
|
- une projection publique explicitement typée, limitée aux champs autorisés ;
|
||||||
|
- un diagnostic borné contenant au plus des états tels que `configured`/`missing` pour les URLs, DSN et chemins sensibles ;
|
||||||
|
- aucune projection construite par sérialisation du runtime suivie d'un masquage a posteriori.
|
||||||
|
|
||||||
|
La sensibilité suit `Secret > Internal > Public`. Une valeur composée hérite de la sensibilité la plus forte des placeholders qu'elle contient ; une URL incorporant `${KS_SECRET_HELIUS_API_KEY}` est donc secrète même si son champ final est simplement `url`.
|
||||||
|
|
||||||
|
La section `application` d'une composition est opaque à `ks-config`. Le desktop la valide avec son schéma `config/schemas/kb-app-demo-desktop.application.config.schema.json`; un futur worker pourra posséder son propre schéma sans modifier `ks-config`.
|
||||||
|
|
||||||
## Frontière TS-RS
|
## Frontière TS-RS
|
||||||
|
|
||||||
L'audit `pre.007` confirme que le frontend du desktop n'importe directement aucun binding généré depuis `ks-config` ou `ks-lib`. Les dérivations TS-RS des crates généralistes seront donc réévaluées dans la prerelease suivante : les DTO réellement destinés à Tauri doivent être définis/wrappés dans l'application, sauf contrat TypeScript générique explicitement justifié.
|
Depuis `pre.008`, `ks-config` et `ks-lib` ne dépendent plus de TS-RS et ne possèdent plus de bindings TypeScript générés. Les DTO traversant Tauri appartiennent à `kb-app-demo-desktop` ou à la future application concernée. Une exception dans une crate `ks-*` exige un contrat TypeScript générique indépendant de Tauri explicitement justifié et audité.
|
||||||
|
|
||||||
## Étape suivante
|
## Étape suivante
|
||||||
|
|
||||||
La prochaine prerelease traite ensemble :
|
`pre.009` est une prerelease de clôture : réconciliation documentaire, audits finaux, nettoyage des TODO, archivage du plan/prompt et préparation de `0.5.2`.
|
||||||
|
|
||||||
- représentation source / runtime / publique / diagnostic ;
|
|
||||||
- propagation `SECRET` / `PUBLIC` / interne ;
|
|
||||||
- suppression de l'exposition Tauri de la configuration runtime complète ;
|
|
||||||
- réduction des bindings TS-RS dans les crates généralistes et wrappers applicatifs nécessaires.
|
|
||||||
|
|
||||||
## Invariants
|
## Invariants
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
<!-- file: docs/plans/V0_5_1_KHADHROONY_SOLANA_NAMESPACE_AND_CONFIG_PLAN.md -->
|
<!-- file: docs/plans/V0_5_1_KHADHROONY_SOLANA_NAMESPACE_AND_CONFIG_PLAN.md -->
|
||||||
<!-- version: 7 -->
|
<!-- version: 8 -->
|
||||||
|
|
||||||
# Plan temporaire `0.5.1` — namespace Khadhroony Solana et configuration sûre
|
# Plan temporaire `0.5.1` — namespace Khadhroony Solana et configuration sûre
|
||||||
|
|
||||||
## 1. Statut et règle de cette prerelease
|
## 1. Statut et règle de cette prerelease
|
||||||
|
|
||||||
Ce document est le plan temporaire de `0.5.1`. Les prereleases `pre.001` à `pre.004` ont fermé l'inventaire puis migré crates, identités techniques et variables d'environnement. `pre.005` a séparé le logging, `pre.006` a introduit les compositions de binaires et extrait transport/listeners, et `pre.007` termine maintenant la décomposition des responsabilités partagées avec store/wallet/execution, valeurs globales hors profils et defaults autonomes. `kb-app-demo-desktop` et le workspace racine restent nommés comme avant.
|
Ce document est le plan temporaire de `0.5.1`. Les prereleases `pre.001` à `pre.004` ont fermé l'inventaire puis migré crates, identités techniques et variables d'environnement. `pre.005` à `pre.007` ont terminé le split logging/transport/listeners/store/wallet/execution, les compositions de binaires et les defaults autonomes. `pre.008` ferme maintenant les frontières source/runtime/public/diagnostic, la non-divulgation et TS-RS. `kb-app-demo-desktop` et le workspace racine restent nommés comme avant.
|
||||||
|
|
||||||
Les contrôles Rust et le démarrage Tauri de `pre.006` ont été validés par l'opérateur le 10 août 2026. Le démarrage confirme le chargement de `kb-app-demo-desktop.default.config.json`, du document logging séparé, des profils transport et du store, avec DSN PostgreSQL masqué dans les logs. `pre.007` doit préserver le comportement runtime tout en changeant l'ownership source des paramètres.
|
Après `pre.007-delta-fix-002`, l'opérateur a validé `cargo fmt`, `cargo check --workspace`, `cargo clippy --all-targets`, l'audit workspace, `cargo test --workspace` et le démarrage Tauri le 10 août 2026. `pre.008` peut donc modifier uniquement les frontières de sortie/configuration sans rouvrir le split structurel déjà validé.
|
||||||
|
|
||||||
## 2. Invariant du workspace racine
|
## 2. Invariant du workspace racine
|
||||||
|
|
||||||
@@ -32,18 +32,18 @@ Les bibliothèques internes Solana utilisent `ks-*` / `ks_*` et leurs variables
|
|||||||
|
|
||||||
## 4. Inventaire des crates et ordre de migration
|
## 4. Inventaire des crates et ordre de migration
|
||||||
|
|
||||||
| Package actuel | Identifiant Rust actuel | Package cible | Identifiant Rust cible | Dépendances workspace directes actuelles | Ordre |
|
| Package actuel | Identifiant Rust actuel | Package cible | Identifiant Rust cible | Dépendances workspace directes actuelles | Ordre |
|
||||||
|---|---|---|---|---|---:|
|
|------------------------------|------------------------------|------------------------------|------------------------------|----------------------------------------------------------------------------------------------------|------:|
|
||||||
| `kb-core` | `kb_core` | `ks-core` | `ks_core` | — | 1 |
|
| `kb-core` | `kb_core` | `ks-core` | `ks_core` | — | 1 |
|
||||||
| `kb-program-ids` | `kb_program_ids` | `ks-program-ids` | `ks_program_ids` | — | 2 |
|
| `kb-program-ids` | `kb_program_ids` | `ks-program-ids` | `ks_program_ids` | — | 2 |
|
||||||
| `kb-config` | `kb_config` | `ks-config` | `ks_config` | kb-core | 3 |
|
| `kb-config` | `kb_config` | `ks-config` | `ks_config` | kb-core | 3 |
|
||||||
| `kb-logging` | `kb_logging` | `ks-logging` | `ks_logging` | kb-core | 4 |
|
| `kb-logging` | `kb_logging` | `ks-logging` | `ks_logging` | kb-core | 4 |
|
||||||
| `kb-wallet` | `kb_wallet` | `ks-wallet` | `ks_wallet` | kb-core | 5 |
|
| `kb-wallet` | `kb_wallet` | `ks-wallet` | `ks_wallet` | kb-core | 5 |
|
||||||
| `kb-lib` | `kb_lib` | `ks-lib` | `ks_lib` | kb-core, kb-program-ids | 6 |
|
| `kb-lib` | `kb_lib` | `ks-lib` | `ks_lib` | kb-core, kb-program-ids | 6 |
|
||||||
| `kb-onchain-transport` | `kb_onchain_transport` | `ks-onchain-transport` | `ks_onchain_transport` | kb-config, kb-core, kb-lib | 7 |
|
| `kb-onchain-transport` | `kb_onchain_transport` | `ks-onchain-transport` | `ks_onchain_transport` | kb-config, kb-core, kb-lib | 7 |
|
||||||
| `kb-store` | `kb_store` | `ks-store` | `ks_store` | kb-core, kb-lib | 8 |
|
| `kb-store` | `kb_store` | `ks-store` | `ks_store` | kb-core, kb-lib | 8 |
|
||||||
| `kb-pipeline` | `kb_pipeline` | `ks-pipeline` | `ks_pipeline` | kb-core, kb-config, kb-lib, kb-onchain-transport, kb-program-ids, kb-store | 9 |
|
| `kb-pipeline` | `kb_pipeline` | `ks-pipeline` | `ks_pipeline` | kb-core, kb-config, kb-lib, kb-onchain-transport, kb-program-ids, kb-store | 9 |
|
||||||
| `kb-pipeline-demo-scenarios` | `kb_pipeline_demo_scenarios` | `ks-pipeline-demo-scenarios` | `ks_pipeline_demo_scenarios` | kb-core, kb-config, kb-lib, kb-onchain-transport, kb-pipeline, kb-program-ids, kb-store, kb-wallet | 10 |
|
| `kb-pipeline-demo-scenarios` | `kb_pipeline_demo_scenarios` | `ks-pipeline-demo-scenarios` | `ks_pipeline_demo_scenarios` | kb-core, kb-config, kb-lib, kb-onchain-transport, kb-pipeline, kb-program-ids, kb-store, kb-wallet | 10 |
|
||||||
|
|
||||||
`kb-app-demo-desktop` est adapté en dernier, mais garde son package, son répertoire et ses identifiants applicatifs.
|
`kb-app-demo-desktop` est adapté en dernier, mais garde son package, son répertoire et ses identifiants applicatifs.
|
||||||
|
|
||||||
@@ -58,18 +58,18 @@ bin : kb-pipeline-demo-scenarios-cli -> ks-pipeline-demo-scenarios-cli
|
|||||||
|
|
||||||
Les valeurs suivantes sont des métriques d'orientation sur les fichiers actifs, hors archives et artefacts générés. Elles montrent qu'un renommage massif en une seule opération serait difficile à diagnostiquer.
|
Les valeurs suivantes sont des métriques d'orientation sur les fichiers actifs, hors archives et artefacts générés. Elles montrent qu'un renommage massif en une seule opération serait difficile à diagnostiquer.
|
||||||
|
|
||||||
| Crate | Références package / fichiers | Références identifiant Rust / fichiers |
|
| Crate | Références package / fichiers | Références identifiant Rust / fichiers |
|
||||||
|---|---:|---:|
|
|------------------------------|------------------------------:|---------------------------------------:|
|
||||||
| `kb-core` | 51 / 32 | 3165 / 407 |
|
| `kb-core` | 51 / 32 | 3165 / 407 |
|
||||||
| `kb-config` | 56 / 33 | 201 / 44 |
|
| `kb-config` | 56 / 33 | 201 / 44 |
|
||||||
| `kb-lib` | 3145 / 550 | 2785 / 97 |
|
| `kb-lib` | 3145 / 550 | 2785 / 97 |
|
||||||
| `kb-logging` | 72 / 27 | 22 / 3 |
|
| `kb-logging` | 72 / 27 | 22 / 3 |
|
||||||
| `kb-program-ids` | 42 / 28 | 1413 / 334 |
|
| `kb-program-ids` | 42 / 28 | 1413 / 334 |
|
||||||
| `kb-pipeline` | 287 / 112 | 436 / 38 |
|
| `kb-pipeline` | 287 / 112 | 436 / 38 |
|
||||||
| `kb-pipeline-demo-scenarios` | 145 / 75 | 173 / 18 |
|
| `kb-pipeline-demo-scenarios` | 145 / 75 | 173 / 18 |
|
||||||
| `kb-onchain-transport` | 125 / 56 | 530 / 50 |
|
| `kb-onchain-transport` | 125 / 56 | 530 / 50 |
|
||||||
| `kb-store` | 157 / 81 | 344 / 30 |
|
| `kb-store` | 157 / 81 | 344 / 30 |
|
||||||
| `kb-wallet` | 75 / 30 | 53 / 17 |
|
| `kb-wallet` | 75 / 30 | 53 / 17 |
|
||||||
|
|
||||||
Le volume `kb-lib` inclut notamment les identités techniques `kb-lib.*`; il ne doit pas être interprété comme autant d'importations Cargo.
|
Le volume `kb-lib` inclut notamment les identités techniques `kb-lib.*`; il ne doit pas être interprété comme autant d'importations Cargo.
|
||||||
|
|
||||||
@@ -145,264 +145,264 @@ Les targets de tracing de crates génériques doivent également migrer vers `ks
|
|||||||
|
|
||||||
### 6.1 Inventaire exhaustif des identités `kb-lib.*`
|
### 6.1 Inventaire exhaustif des identités `kb-lib.*`
|
||||||
|
|
||||||
| Identité actuelle | Identité cible |
|
| Identité actuelle | Identité cible |
|
||||||
|---|---|
|
|----------------------------------------------------------------|----------------------------------------------------------------|
|
||||||
| `kb-lib.decoder.adapter.saber_decimal_wrapper` | `ks-lib-decoder.adapter.saber_decimal_wrapper` |
|
| `kb-lib.decoder.adapter.saber_decimal_wrapper` | `ks-lib-decoder.adapter.saber_decimal_wrapper` |
|
||||||
| `kb-lib.decoder.adapter.spl_token_wrap` | `ks-lib-decoder.adapter.spl_token_wrap` |
|
| `kb-lib.decoder.adapter.spl_token_wrap` | `ks-lib-decoder.adapter.spl_token_wrap` |
|
||||||
| `kb-lib.decoder.admin.jupiter_lock` | `ks-lib-decoder.admin.jupiter_lock` |
|
| `kb-lib.decoder.admin.jupiter_lock` | `ks-lib-decoder.admin.jupiter_lock` |
|
||||||
| `kb-lib.decoder.admin.pump_fees` | `ks-lib-decoder.admin.pump_fees` |
|
| `kb-lib.decoder.admin.pump_fees` | `ks-lib-decoder.admin.pump_fees` |
|
||||||
| `kb-lib.decoder.amm.aldrin_v1` | `ks-lib-decoder.amm.aldrin_v1` |
|
| `kb-lib.decoder.amm.aldrin_v1` | `ks-lib-decoder.amm.aldrin_v1` |
|
||||||
| `kb-lib.decoder.amm.aldrin_v2` | `ks-lib-decoder.amm.aldrin_v2` |
|
| `kb-lib.decoder.amm.aldrin_v2` | `ks-lib-decoder.amm.aldrin_v2` |
|
||||||
| `kb-lib.decoder.amm.alphaq` | `ks-lib-decoder.amm.alphaq` |
|
| `kb-lib.decoder.amm.alphaq` | `ks-lib-decoder.amm.alphaq` |
|
||||||
| `kb-lib.decoder.amm.believe` | `ks-lib-decoder.amm.believe` |
|
| `kb-lib.decoder.amm.believe` | `ks-lib-decoder.amm.believe` |
|
||||||
| `kb-lib.decoder.amm.bonk_swap` | `ks-lib-decoder.amm.bonk_swap` |
|
| `kb-lib.decoder.amm.bonk_swap` | `ks-lib-decoder.amm.bonk_swap` |
|
||||||
| `kb-lib.decoder.amm.fluxbeam` | `ks-lib-decoder.amm.fluxbeam` |
|
| `kb-lib.decoder.amm.fluxbeam` | `ks-lib-decoder.amm.fluxbeam` |
|
||||||
| `kb-lib.decoder.amm.goon_fi` | `ks-lib-decoder.amm.goon_fi` |
|
| `kb-lib.decoder.amm.goon_fi` | `ks-lib-decoder.amm.goon_fi` |
|
||||||
| `kb-lib.decoder.amm.goosefx_gamma` | `ks-lib-decoder.amm.goosefx_gamma` |
|
| `kb-lib.decoder.amm.goosefx_gamma` | `ks-lib-decoder.amm.goosefx_gamma` |
|
||||||
| `kb-lib.decoder.amm.goosefx_v2` | `ks-lib-decoder.amm.goosefx_v2` |
|
| `kb-lib.decoder.amm.goosefx_v2` | `ks-lib-decoder.amm.goosefx_v2` |
|
||||||
| `kb-lib.decoder.amm.guac_swap` | `ks-lib-decoder.amm.guac_swap` |
|
| `kb-lib.decoder.amm.guac_swap` | `ks-lib-decoder.amm.guac_swap` |
|
||||||
| `kb-lib.decoder.amm.lifinity_swap_v2` | `ks-lib-decoder.amm.lifinity_swap_v2` |
|
| `kb-lib.decoder.amm.lifinity_swap_v2` | `ks-lib-decoder.amm.lifinity_swap_v2` |
|
||||||
| `kb-lib.decoder.amm.metadao_futarchy_amm` | `ks-lib-decoder.amm.metadao_futarchy_amm` |
|
| `kb-lib.decoder.amm.metadao_futarchy_amm` | `ks-lib-decoder.amm.metadao_futarchy_amm` |
|
||||||
| `kb-lib.decoder.amm.metadao_v0_5` | `ks-lib-decoder.amm.metadao_v0_5` |
|
| `kb-lib.decoder.amm.metadao_v0_5` | `ks-lib-decoder.amm.metadao_v0_5` |
|
||||||
| `kb-lib.decoder.amm.meteora_damm_v1` | `ks-lib-decoder.amm.meteora_damm_v1` |
|
| `kb-lib.decoder.amm.meteora_damm_v1` | `ks-lib-decoder.amm.meteora_damm_v1` |
|
||||||
| `kb-lib.decoder.amm.meteora_damm_v2` | `ks-lib-decoder.amm.meteora_damm_v2` |
|
| `kb-lib.decoder.amm.meteora_damm_v2` | `ks-lib-decoder.amm.meteora_damm_v2` |
|
||||||
| `kb-lib.decoder.amm.obric_v2` | `ks-lib-decoder.amm.obric_v2` |
|
| `kb-lib.decoder.amm.obric_v2` | `ks-lib-decoder.amm.obric_v2` |
|
||||||
| `kb-lib.decoder.amm.one_dex` | `ks-lib-decoder.amm.one_dex` |
|
| `kb-lib.decoder.amm.one_dex` | `ks-lib-decoder.amm.one_dex` |
|
||||||
| `kb-lib.decoder.amm.pump_swap` | `ks-lib-decoder.amm.pump_swap` |
|
| `kb-lib.decoder.amm.pump_swap` | `ks-lib-decoder.amm.pump_swap` |
|
||||||
| `kb-lib.decoder.amm.raydium_lp_v4` | `ks-lib-decoder.amm.raydium_lp_v4` |
|
| `kb-lib.decoder.amm.raydium_lp_v4` | `ks-lib-decoder.amm.raydium_lp_v4` |
|
||||||
| `kb-lib.decoder.amm.solfi` | `ks-lib-decoder.amm.solfi` |
|
| `kb-lib.decoder.amm.solfi` | `ks-lib-decoder.amm.solfi` |
|
||||||
| `kb-lib.decoder.amm.solfi_v2` | `ks-lib-decoder.amm.solfi_v2` |
|
| `kb-lib.decoder.amm.solfi_v2` | `ks-lib-decoder.amm.solfi_v2` |
|
||||||
| `kb-lib.decoder.amm.vertigo` | `ks-lib-decoder.amm.vertigo` |
|
| `kb-lib.decoder.amm.vertigo` | `ks-lib-decoder.amm.vertigo` |
|
||||||
| `kb-lib.decoder.amm.virtuals` | `ks-lib-decoder.amm.virtuals` |
|
| `kb-lib.decoder.amm.virtuals` | `ks-lib-decoder.amm.virtuals` |
|
||||||
| `kb-lib.decoder.amm.woofi` | `ks-lib-decoder.amm.woofi` |
|
| `kb-lib.decoder.amm.woofi` | `ks-lib-decoder.amm.woofi` |
|
||||||
| `kb-lib.decoder.amm.zero_fi` | `ks-lib-decoder.amm.zero_fi` |
|
| `kb-lib.decoder.amm.zero_fi` | `ks-lib-decoder.amm.zero_fi` |
|
||||||
| `kb-lib.decoder.amm.zora` | `ks-lib-decoder.amm.zora` |
|
| `kb-lib.decoder.amm.zora` | `ks-lib-decoder.amm.zora` |
|
||||||
| `kb-lib.decoder.anchor` | `ks-lib-decoder.anchor` |
|
| `kb-lib.decoder.anchor` | `ks-lib-decoder.anchor` |
|
||||||
| `kb-lib.decoder.api` | `ks-lib-decoder.api` |
|
| `kb-lib.decoder.api` | `ks-lib-decoder.api` |
|
||||||
| `kb-lib.decoder.bridge.circle_cctp_token_messenger_minter` | `ks-lib-decoder.bridge.circle_cctp_token_messenger_minter` |
|
| `kb-lib.decoder.bridge.circle_cctp_token_messenger_minter` | `ks-lib-decoder.bridge.circle_cctp_token_messenger_minter` |
|
||||||
| `kb-lib.decoder.bridge.circle_cctp_token_messenger_minter_v2` | `ks-lib-decoder.bridge.circle_cctp_token_messenger_minter_v2` |
|
| `kb-lib.decoder.bridge.circle_cctp_token_messenger_minter_v2` | `ks-lib-decoder.bridge.circle_cctp_token_messenger_minter_v2` |
|
||||||
| `kb-lib.decoder.bridge.layer_zero_endpoint` | `ks-lib-decoder.bridge.layer_zero_endpoint` |
|
| `kb-lib.decoder.bridge.layer_zero_endpoint` | `ks-lib-decoder.bridge.layer_zero_endpoint` |
|
||||||
| `kb-lib.decoder.bridge.layer_zero_executor` | `ks-lib-decoder.bridge.layer_zero_executor` |
|
| `kb-lib.decoder.bridge.layer_zero_executor` | `ks-lib-decoder.bridge.layer_zero_executor` |
|
||||||
| `kb-lib.decoder.clmm.byreal` | `ks-lib-decoder.clmm.byreal` |
|
| `kb-lib.decoder.clmm.byreal` | `ks-lib-decoder.clmm.byreal` |
|
||||||
| `kb-lib.decoder.clmm.fusion` | `ks-lib-decoder.clmm.fusion` |
|
| `kb-lib.decoder.clmm.fusion` | `ks-lib-decoder.clmm.fusion` |
|
||||||
| `kb-lib.decoder.clmm.orca_whirlpool` | `ks-lib-decoder.clmm.orca_whirlpool` |
|
| `kb-lib.decoder.clmm.orca_whirlpool` | `ks-lib-decoder.clmm.orca_whirlpool` |
|
||||||
| `kb-lib.decoder.clmm.pancake_swap` | `ks-lib-decoder.clmm.pancake_swap` |
|
| `kb-lib.decoder.clmm.pancake_swap` | `ks-lib-decoder.clmm.pancake_swap` |
|
||||||
| `kb-lib.decoder.clmm.raydium` | `ks-lib-decoder.clmm.raydium` |
|
| `kb-lib.decoder.clmm.raydium` | `ks-lib-decoder.clmm.raydium` |
|
||||||
| `kb-lib.decoder.clmm.stabble` | `ks-lib-decoder.clmm.stabble` |
|
| `kb-lib.decoder.clmm.stabble` | `ks-lib-decoder.clmm.stabble` |
|
||||||
| `kb-lib.decoder.cpmm.raydium` | `ks-lib-decoder.cpmm.raydium` |
|
| `kb-lib.decoder.cpmm.raydium` | `ks-lib-decoder.cpmm.raydium` |
|
||||||
| `kb-lib.decoder.dlmm.meteora` | `ks-lib-decoder.dlmm.meteora` |
|
| `kb-lib.decoder.dlmm.meteora` | `ks-lib-decoder.dlmm.meteora` |
|
||||||
| `kb-lib.decoder.fees.bags_fee_share_v1` | `ks-lib-decoder.fees.bags_fee_share_v1` |
|
| `kb-lib.decoder.fees.bags_fee_share_v1` | `ks-lib-decoder.fees.bags_fee_share_v1` |
|
||||||
| `kb-lib.decoder.fees.bags_fee_share_v2` | `ks-lib-decoder.fees.bags_fee_share_v2` |
|
| `kb-lib.decoder.fees.bags_fee_share_v2` | `ks-lib-decoder.fees.bags_fee_share_v2` |
|
||||||
| `kb-lib.decoder.fees.pump_fees` | `ks-lib-decoder.fees.pump_fees` |
|
| `kb-lib.decoder.fees.pump_fees` | `ks-lib-decoder.fees.pump_fees` |
|
||||||
| `kb-lib.decoder.governance.metadao_bid_wall` | `ks-lib-decoder.governance.metadao_bid_wall` |
|
| `kb-lib.decoder.governance.metadao_bid_wall` | `ks-lib-decoder.governance.metadao_bid_wall` |
|
||||||
| `kb-lib.decoder.governance.metadao_futarchy` | `ks-lib-decoder.governance.metadao_futarchy` |
|
| `kb-lib.decoder.governance.metadao_futarchy` | `ks-lib-decoder.governance.metadao_futarchy` |
|
||||||
| `kb-lib.decoder.governance.squads_multisig` | `ks-lib-decoder.governance.squads_multisig` |
|
| `kb-lib.decoder.governance.squads_multisig` | `ks-lib-decoder.governance.squads_multisig` |
|
||||||
| `kb-lib.decoder.launchpad.boop_fun` | `ks-lib-decoder.launchpad.boop_fun` |
|
| `kb-lib.decoder.launchpad.boop_fun` | `ks-lib-decoder.launchpad.boop_fun` |
|
||||||
| `kb-lib.decoder.launchpad.metadao_ico` | `ks-lib-decoder.launchpad.metadao_ico` |
|
| `kb-lib.decoder.launchpad.metadao_ico` | `ks-lib-decoder.launchpad.metadao_ico` |
|
||||||
| `kb-lib.decoder.launchpad.meteora_dbc` | `ks-lib-decoder.launchpad.meteora_dbc` |
|
| `kb-lib.decoder.launchpad.meteora_dbc` | `ks-lib-decoder.launchpad.meteora_dbc` |
|
||||||
| `kb-lib.decoder.launchpad.moonit` | `ks-lib-decoder.launchpad.moonit` |
|
| `kb-lib.decoder.launchpad.moonit` | `ks-lib-decoder.launchpad.moonit` |
|
||||||
| `kb-lib.decoder.launchpad.orca_wavebreak` | `ks-lib-decoder.launchpad.orca_wavebreak` |
|
| `kb-lib.decoder.launchpad.orca_wavebreak` | `ks-lib-decoder.launchpad.orca_wavebreak` |
|
||||||
| `kb-lib.decoder.launchpad.printr` | `ks-lib-decoder.launchpad.printr` |
|
| `kb-lib.decoder.launchpad.printr` | `ks-lib-decoder.launchpad.printr` |
|
||||||
| `kb-lib.decoder.launchpad.pump_fun` | `ks-lib-decoder.launchpad.pump_fun` |
|
| `kb-lib.decoder.launchpad.pump_fun` | `ks-lib-decoder.launchpad.pump_fun` |
|
||||||
| `kb-lib.decoder.launchpad.pump_pumpup_ai` | `ks-lib-decoder.launchpad.pump_pumpup_ai` |
|
| `kb-lib.decoder.launchpad.pump_pumpup_ai` | `ks-lib-decoder.launchpad.pump_pumpup_ai` |
|
||||||
| `kb-lib.decoder.launchpad.raydium_launchlab` | `ks-lib-decoder.launchpad.raydium_launchlab` |
|
| `kb-lib.decoder.launchpad.raydium_launchlab` | `ks-lib-decoder.launchpad.raydium_launchlab` |
|
||||||
| `kb-lib.decoder.launchpad.virtuals` | `ks-lib-decoder.launchpad.virtuals` |
|
| `kb-lib.decoder.launchpad.virtuals` | `ks-lib-decoder.launchpad.virtuals` |
|
||||||
| `kb-lib.decoder.lending.clone` | `ks-lib-decoder.lending.clone` |
|
| `kb-lib.decoder.lending.clone` | `ks-lib-decoder.lending.clone` |
|
||||||
| `kb-lib.decoder.lending.jupiter_lend_borrow` | `ks-lib-decoder.lending.jupiter_lend_borrow` |
|
| `kb-lib.decoder.lending.jupiter_lend_borrow` | `ks-lib-decoder.lending.jupiter_lend_borrow` |
|
||||||
| `kb-lib.decoder.lending.jupiter_lend_earn` | `ks-lib-decoder.lending.jupiter_lend_earn` |
|
| `kb-lib.decoder.lending.jupiter_lend_earn` | `ks-lib-decoder.lending.jupiter_lend_earn` |
|
||||||
| `kb-lib.decoder.lending.jupiter_lend_flash_loan` | `ks-lib-decoder.lending.jupiter_lend_flash_loan` |
|
| `kb-lib.decoder.lending.jupiter_lend_flash_loan` | `ks-lib-decoder.lending.jupiter_lend_flash_loan` |
|
||||||
| `kb-lib.decoder.lending.jupiter_lend_liquidity` | `ks-lib-decoder.lending.jupiter_lend_liquidity` |
|
| `kb-lib.decoder.lending.jupiter_lend_liquidity` | `ks-lib-decoder.lending.jupiter_lend_liquidity` |
|
||||||
| `kb-lib.decoder.lending.kamino` | `ks-lib-decoder.lending.kamino` |
|
| `kb-lib.decoder.lending.kamino` | `ks-lib-decoder.lending.kamino` |
|
||||||
| `kb-lib.decoder.lending.marginfi_v2` | `ks-lib-decoder.lending.marginfi_v2` |
|
| `kb-lib.decoder.lending.marginfi_v2` | `ks-lib-decoder.lending.marginfi_v2` |
|
||||||
| `kb-lib.decoder.lock.raydium_lp` | `ks-lib-decoder.lock.raydium_lp` |
|
| `kb-lib.decoder.lock.raydium_lp` | `ks-lib-decoder.lock.raydium_lp` |
|
||||||
| `kb-lib.decoder.metadata.metaplex_token_metadata` | `ks-lib-decoder.metadata.metaplex_token_metadata` |
|
| `kb-lib.decoder.metadata.metaplex_token_metadata` | `ks-lib-decoder.metadata.metaplex_token_metadata` |
|
||||||
| `kb-lib.decoder.metadata.solana_program_metadata` | `ks-lib-decoder.metadata.solana_program_metadata` |
|
| `kb-lib.decoder.metadata.solana_program_metadata` | `ks-lib-decoder.metadata.solana_program_metadata` |
|
||||||
| `kb-lib.decoder.metadata.spl_name_service` | `ks-lib-decoder.metadata.spl_name_service` |
|
| `kb-lib.decoder.metadata.spl_name_service` | `ks-lib-decoder.metadata.spl_name_service` |
|
||||||
| `kb-lib.decoder.nft.metaplex_bubblegum` | `ks-lib-decoder.nft.metaplex_bubblegum` |
|
| `kb-lib.decoder.nft.metaplex_bubblegum` | `ks-lib-decoder.nft.metaplex_bubblegum` |
|
||||||
| `kb-lib.decoder.nft.tensor_cnft` | `ks-lib-decoder.nft.tensor_cnft` |
|
| `kb-lib.decoder.nft.tensor_cnft` | `ks-lib-decoder.nft.tensor_cnft` |
|
||||||
| `kb-lib.decoder.orderbook.jupiter_limit_order` | `ks-lib-decoder.orderbook.jupiter_limit_order` |
|
| `kb-lib.decoder.orderbook.jupiter_limit_order` | `ks-lib-decoder.orderbook.jupiter_limit_order` |
|
||||||
| `kb-lib.decoder.orderbook.jupiter_limit_order_v2` | `ks-lib-decoder.orderbook.jupiter_limit_order_v2` |
|
| `kb-lib.decoder.orderbook.jupiter_limit_order_v2` | `ks-lib-decoder.orderbook.jupiter_limit_order_v2` |
|
||||||
| `kb-lib.decoder.orderbook.openbook_v2` | `ks-lib-decoder.orderbook.openbook_v2` |
|
| `kb-lib.decoder.orderbook.openbook_v2` | `ks-lib-decoder.orderbook.openbook_v2` |
|
||||||
| `kb-lib.decoder.perpetuals.drift_v2` | `ks-lib-decoder.perpetuals.drift_v2` |
|
| `kb-lib.decoder.perpetuals.drift_v2` | `ks-lib-decoder.perpetuals.drift_v2` |
|
||||||
| `kb-lib.decoder.perpetuals.jupiter` | `ks-lib-decoder.perpetuals.jupiter` |
|
| `kb-lib.decoder.perpetuals.jupiter` | `ks-lib-decoder.perpetuals.jupiter` |
|
||||||
| `kb-lib.decoder.perpetuals.phoenix_eternal` | `ks-lib-decoder.perpetuals.phoenix_eternal` |
|
| `kb-lib.decoder.perpetuals.phoenix_eternal` | `ks-lib-decoder.perpetuals.phoenix_eternal` |
|
||||||
| `kb-lib.decoder.perpetuals.zeta` | `ks-lib-decoder.perpetuals.zeta` |
|
| `kb-lib.decoder.perpetuals.zeta` | `ks-lib-decoder.perpetuals.zeta` |
|
||||||
| `kb-lib.decoder.router.dflow_aggregator_v4` | `ks-lib-decoder.router.dflow_aggregator_v4` |
|
| `kb-lib.decoder.router.dflow_aggregator_v4` | `ks-lib-decoder.router.dflow_aggregator_v4` |
|
||||||
| `kb-lib.decoder.router.jupiter_aggregator_v4` | `ks-lib-decoder.router.jupiter_aggregator_v4` |
|
| `kb-lib.decoder.router.jupiter_aggregator_v4` | `ks-lib-decoder.router.jupiter_aggregator_v4` |
|
||||||
| `kb-lib.decoder.router.jupiter_aggregator_v6` | `ks-lib-decoder.router.jupiter_aggregator_v6` |
|
| `kb-lib.decoder.router.jupiter_aggregator_v6` | `ks-lib-decoder.router.jupiter_aggregator_v6` |
|
||||||
| `kb-lib.decoder.router.jupiter_dca` | `ks-lib-decoder.router.jupiter_dca` |
|
| `kb-lib.decoder.router.jupiter_dca` | `ks-lib-decoder.router.jupiter_dca` |
|
||||||
| `kb-lib.decoder.router.okx_labs_v1` | `ks-lib-decoder.router.okx_labs_v1` |
|
| `kb-lib.decoder.router.okx_labs_v1` | `ks-lib-decoder.router.okx_labs_v1` |
|
||||||
| `kb-lib.decoder.router.okx_labs_v2` | `ks-lib-decoder.router.okx_labs_v2` |
|
| `kb-lib.decoder.router.okx_labs_v2` | `ks-lib-decoder.router.okx_labs_v2` |
|
||||||
| `kb-lib.decoder.rwa.ondo_global_markets` | `ks-lib-decoder.rwa.ondo_global_markets` |
|
| `kb-lib.decoder.rwa.ondo_global_markets` | `ks-lib-decoder.rwa.ondo_global_markets` |
|
||||||
| `kb-lib.decoder.solana.core` | `ks-lib-decoder.solana.core` |
|
| `kb-lib.decoder.solana.core` | `ks-lib-decoder.solana.core` |
|
||||||
| `kb-lib.decoder.spl.account_compression` | `ks-lib-decoder.spl.account_compression` |
|
| `kb-lib.decoder.spl.account_compression` | `ks-lib-decoder.spl.account_compression` |
|
||||||
| `kb-lib.decoder.spl.associated_token_account` | `ks-lib-decoder.spl.associated_token_account` |
|
| `kb-lib.decoder.spl.associated_token_account` | `ks-lib-decoder.spl.associated_token_account` |
|
||||||
| `kb-lib.decoder.spl.elgamal_registry` | `ks-lib-decoder.spl.elgamal_registry` |
|
| `kb-lib.decoder.spl.elgamal_registry` | `ks-lib-decoder.spl.elgamal_registry` |
|
||||||
| `kb-lib.decoder.spl.memo` | `ks-lib-decoder.spl.memo` |
|
| `kb-lib.decoder.spl.memo` | `ks-lib-decoder.spl.memo` |
|
||||||
| `kb-lib.decoder.spl.noop` | `ks-lib-decoder.spl.noop` |
|
| `kb-lib.decoder.spl.noop` | `ks-lib-decoder.spl.noop` |
|
||||||
| `kb-lib.decoder.spl.single_pool` | `ks-lib-decoder.spl.single_pool` |
|
| `kb-lib.decoder.spl.single_pool` | `ks-lib-decoder.spl.single_pool` |
|
||||||
| `kb-lib.decoder.spl.stake_pool` | `ks-lib-decoder.spl.stake_pool` |
|
| `kb-lib.decoder.spl.stake_pool` | `ks-lib-decoder.spl.stake_pool` |
|
||||||
| `kb-lib.decoder.spl.token` | `ks-lib-decoder.spl.token` |
|
| `kb-lib.decoder.spl.token` | `ks-lib-decoder.spl.token` |
|
||||||
| `kb-lib.decoder.spl.token_2022` | `ks-lib-decoder.spl.token_2022` |
|
| `kb-lib.decoder.spl.token_2022` | `ks-lib-decoder.spl.token_2022` |
|
||||||
| `kb-lib.decoder.stable.swap_hylo_exchange` | `ks-lib-decoder.stable.swap_hylo_exchange` |
|
| `kb-lib.decoder.stable.swap_hylo_exchange` | `ks-lib-decoder.stable.swap_hylo_exchange` |
|
||||||
| `kb-lib.decoder.stable.swap_jupiter_stable` | `ks-lib-decoder.stable.swap_jupiter_stable` |
|
| `kb-lib.decoder.stable.swap_jupiter_stable` | `ks-lib-decoder.stable.swap_jupiter_stable` |
|
||||||
| `kb-lib.decoder.stable.swap_numeraire` | `ks-lib-decoder.stable.swap_numeraire` |
|
| `kb-lib.decoder.stable.swap_numeraire` | `ks-lib-decoder.stable.swap_numeraire` |
|
||||||
| `kb-lib.decoder.stable.swap_stabble` | `ks-lib-decoder.stable.swap_stabble` |
|
| `kb-lib.decoder.stable.swap_stabble` | `ks-lib-decoder.stable.swap_stabble` |
|
||||||
| `kb-lib.decoder.staking.jito_tip_distribution` | `ks-lib-decoder.staking.jito_tip_distribution` |
|
| `kb-lib.decoder.staking.jito_tip_distribution` | `ks-lib-decoder.staking.jito_tip_distribution` |
|
||||||
| `kb-lib.decoder.staking.kamino_farm` | `ks-lib-decoder.staking.kamino_farm` |
|
| `kb-lib.decoder.staking.kamino_farm` | `ks-lib-decoder.staking.kamino_farm` |
|
||||||
| `kb-lib.decoder.staking.marinade_finance` | `ks-lib-decoder.staking.marinade_finance` |
|
| `kb-lib.decoder.staking.marinade_finance` | `ks-lib-decoder.staking.marinade_finance` |
|
||||||
| `kb-lib.decoder.staking.solayer` | `ks-lib-decoder.staking.solayer` |
|
| `kb-lib.decoder.staking.solayer` | `ks-lib-decoder.staking.solayer` |
|
||||||
| `kb-lib.decoder.storage.solana_record` | `ks-lib-decoder.storage.solana_record` |
|
| `kb-lib.decoder.storage.solana_record` | `ks-lib-decoder.storage.solana_record` |
|
||||||
| `kb-lib.decoder.strategy.jupiter_dca` | `ks-lib-decoder.strategy.jupiter_dca` |
|
| `kb-lib.decoder.strategy.jupiter_dca` | `ks-lib-decoder.strategy.jupiter_dca` |
|
||||||
| `kb-lib.decoder.treasury.helium_treasury_management` | `ks-lib-decoder.treasury.helium_treasury_management` |
|
| `kb-lib.decoder.treasury.helium_treasury_management` | `ks-lib-decoder.treasury.helium_treasury_management` |
|
||||||
| `kb-lib.decoder.vault.carrot_defi` | `ks-lib-decoder.vault.carrot_defi` |
|
| `kb-lib.decoder.vault.carrot_defi` | `ks-lib-decoder.vault.carrot_defi` |
|
||||||
| `kb-lib.decoder.vault.hylo_stability_pool` | `ks-lib-decoder.vault.hylo_stability_pool` |
|
| `kb-lib.decoder.vault.hylo_stability_pool` | `ks-lib-decoder.vault.hylo_stability_pool` |
|
||||||
| `kb-lib.decoder.vault.kamino` | `ks-lib-decoder.vault.kamino` |
|
| `kb-lib.decoder.vault.kamino` | `ks-lib-decoder.vault.kamino` |
|
||||||
| `kb-lib.decoder.vault.kamino_v2` | `ks-lib-decoder.vault.kamino_v2` |
|
| `kb-lib.decoder.vault.kamino_v2` | `ks-lib-decoder.vault.kamino_v2` |
|
||||||
| `kb-lib.decoder.vault.kamino_yvaults` | `ks-lib-decoder.vault.kamino_yvaults` |
|
| `kb-lib.decoder.vault.kamino_yvaults` | `ks-lib-decoder.vault.kamino_yvaults` |
|
||||||
| `kb-lib.decoder.vault.meteora` | `ks-lib-decoder.vault.meteora` |
|
| `kb-lib.decoder.vault.meteora` | `ks-lib-decoder.vault.meteora` |
|
||||||
| `kb-lib.decoder.vesting.jupiter_lock` | `ks-lib-decoder.vesting.jupiter_lock` |
|
| `kb-lib.decoder.vesting.jupiter_lock` | `ks-lib-decoder.vesting.jupiter_lock` |
|
||||||
| `kb-lib.decoder.vesting.streamflow` | `ks-lib-decoder.vesting.streamflow` |
|
| `kb-lib.decoder.vesting.streamflow` | `ks-lib-decoder.vesting.streamflow` |
|
||||||
| `kb-lib.decoder.wallet.jupiter_apepro_smart_wallet` | `ks-lib-decoder.wallet.jupiter_apepro_smart_wallet` |
|
| `kb-lib.decoder.wallet.jupiter_apepro_smart_wallet` | `ks-lib-decoder.wallet.jupiter_apepro_smart_wallet` |
|
||||||
| `kb-lib.decoder.weighted.swap_stabble` | `ks-lib-decoder.weighted.swap_stabble` |
|
| `kb-lib.decoder.weighted.swap_stabble` | `ks-lib-decoder.weighted.swap_stabble` |
|
||||||
| `kb-lib.executor.adapter.saber_decimal_wrapper` | `ks-lib-executor.adapter.saber_decimal_wrapper` |
|
| `kb-lib.executor.adapter.saber_decimal_wrapper` | `ks-lib-executor.adapter.saber_decimal_wrapper` |
|
||||||
| `kb-lib.executor.adapter.spl_token_wrap` | `ks-lib-executor.adapter.spl_token_wrap` |
|
| `kb-lib.executor.adapter.spl_token_wrap` | `ks-lib-executor.adapter.spl_token_wrap` |
|
||||||
| `kb-lib.executor.amm.aldrin_v1` | `ks-lib-executor.amm.aldrin_v1` |
|
| `kb-lib.executor.amm.aldrin_v1` | `ks-lib-executor.amm.aldrin_v1` |
|
||||||
| `kb-lib.executor.amm.aldrin_v2` | `ks-lib-executor.amm.aldrin_v2` |
|
| `kb-lib.executor.amm.aldrin_v2` | `ks-lib-executor.amm.aldrin_v2` |
|
||||||
| `kb-lib.executor.amm.alphaq` | `ks-lib-executor.amm.alphaq` |
|
| `kb-lib.executor.amm.alphaq` | `ks-lib-executor.amm.alphaq` |
|
||||||
| `kb-lib.executor.amm.believe` | `ks-lib-executor.amm.believe` |
|
| `kb-lib.executor.amm.believe` | `ks-lib-executor.amm.believe` |
|
||||||
| `kb-lib.executor.amm.bonk_swap` | `ks-lib-executor.amm.bonk_swap` |
|
| `kb-lib.executor.amm.bonk_swap` | `ks-lib-executor.amm.bonk_swap` |
|
||||||
| `kb-lib.executor.amm.fluxbeam` | `ks-lib-executor.amm.fluxbeam` |
|
| `kb-lib.executor.amm.fluxbeam` | `ks-lib-executor.amm.fluxbeam` |
|
||||||
| `kb-lib.executor.amm.goon_fi` | `ks-lib-executor.amm.goon_fi` |
|
| `kb-lib.executor.amm.goon_fi` | `ks-lib-executor.amm.goon_fi` |
|
||||||
| `kb-lib.executor.amm.goosefx_gamma` | `ks-lib-executor.amm.goosefx_gamma` |
|
| `kb-lib.executor.amm.goosefx_gamma` | `ks-lib-executor.amm.goosefx_gamma` |
|
||||||
| `kb-lib.executor.amm.goosefx_v2` | `ks-lib-executor.amm.goosefx_v2` |
|
| `kb-lib.executor.amm.goosefx_v2` | `ks-lib-executor.amm.goosefx_v2` |
|
||||||
| `kb-lib.executor.amm.guac_swap` | `ks-lib-executor.amm.guac_swap` |
|
| `kb-lib.executor.amm.guac_swap` | `ks-lib-executor.amm.guac_swap` |
|
||||||
| `kb-lib.executor.amm.lifinity_swap_v2` | `ks-lib-executor.amm.lifinity_swap_v2` |
|
| `kb-lib.executor.amm.lifinity_swap_v2` | `ks-lib-executor.amm.lifinity_swap_v2` |
|
||||||
| `kb-lib.executor.amm.metadao_v0_5` | `ks-lib-executor.amm.metadao_v0_5` |
|
| `kb-lib.executor.amm.metadao_v0_5` | `ks-lib-executor.amm.metadao_v0_5` |
|
||||||
| `kb-lib.executor.amm.meteora_damm_v1` | `ks-lib-executor.amm.meteora_damm_v1` |
|
| `kb-lib.executor.amm.meteora_damm_v1` | `ks-lib-executor.amm.meteora_damm_v1` |
|
||||||
| `kb-lib.executor.amm.meteora_damm_v2` | `ks-lib-executor.amm.meteora_damm_v2` |
|
| `kb-lib.executor.amm.meteora_damm_v2` | `ks-lib-executor.amm.meteora_damm_v2` |
|
||||||
| `kb-lib.executor.amm.obric_v2` | `ks-lib-executor.amm.obric_v2` |
|
| `kb-lib.executor.amm.obric_v2` | `ks-lib-executor.amm.obric_v2` |
|
||||||
| `kb-lib.executor.amm.one_dex` | `ks-lib-executor.amm.one_dex` |
|
| `kb-lib.executor.amm.one_dex` | `ks-lib-executor.amm.one_dex` |
|
||||||
| `kb-lib.executor.amm.pump_swap` | `ks-lib-executor.amm.pump_swap` |
|
| `kb-lib.executor.amm.pump_swap` | `ks-lib-executor.amm.pump_swap` |
|
||||||
| `kb-lib.executor.amm.raydium_lp_v4` | `ks-lib-executor.amm.raydium_lp_v4` |
|
| `kb-lib.executor.amm.raydium_lp_v4` | `ks-lib-executor.amm.raydium_lp_v4` |
|
||||||
| `kb-lib.executor.amm.solfi` | `ks-lib-executor.amm.solfi` |
|
| `kb-lib.executor.amm.solfi` | `ks-lib-executor.amm.solfi` |
|
||||||
| `kb-lib.executor.amm.solfi_v2` | `ks-lib-executor.amm.solfi_v2` |
|
| `kb-lib.executor.amm.solfi_v2` | `ks-lib-executor.amm.solfi_v2` |
|
||||||
| `kb-lib.executor.amm.vertigo` | `ks-lib-executor.amm.vertigo` |
|
| `kb-lib.executor.amm.vertigo` | `ks-lib-executor.amm.vertigo` |
|
||||||
| `kb-lib.executor.amm.woofi` | `ks-lib-executor.amm.woofi` |
|
| `kb-lib.executor.amm.woofi` | `ks-lib-executor.amm.woofi` |
|
||||||
| `kb-lib.executor.amm.zero_fi` | `ks-lib-executor.amm.zero_fi` |
|
| `kb-lib.executor.amm.zero_fi` | `ks-lib-executor.amm.zero_fi` |
|
||||||
| `kb-lib.executor.amm.zora` | `ks-lib-executor.amm.zora` |
|
| `kb-lib.executor.amm.zora` | `ks-lib-executor.amm.zora` |
|
||||||
| `kb-lib.executor.bridge.circle_cctp_token_messenger_minter` | `ks-lib-executor.bridge.circle_cctp_token_messenger_minter` |
|
| `kb-lib.executor.bridge.circle_cctp_token_messenger_minter` | `ks-lib-executor.bridge.circle_cctp_token_messenger_minter` |
|
||||||
| `kb-lib.executor.bridge.circle_cctp_token_messenger_minter_v2` | `ks-lib-executor.bridge.circle_cctp_token_messenger_minter_v2` |
|
| `kb-lib.executor.bridge.circle_cctp_token_messenger_minter_v2` | `ks-lib-executor.bridge.circle_cctp_token_messenger_minter_v2` |
|
||||||
| `kb-lib.executor.bridge.layer_zero_endpoint` | `ks-lib-executor.bridge.layer_zero_endpoint` |
|
| `kb-lib.executor.bridge.layer_zero_endpoint` | `ks-lib-executor.bridge.layer_zero_endpoint` |
|
||||||
| `kb-lib.executor.bridge.layer_zero_executor` | `ks-lib-executor.bridge.layer_zero_executor` |
|
| `kb-lib.executor.bridge.layer_zero_executor` | `ks-lib-executor.bridge.layer_zero_executor` |
|
||||||
| `kb-lib.executor.clmm.byreal` | `ks-lib-executor.clmm.byreal` |
|
| `kb-lib.executor.clmm.byreal` | `ks-lib-executor.clmm.byreal` |
|
||||||
| `kb-lib.executor.clmm.fusion` | `ks-lib-executor.clmm.fusion` |
|
| `kb-lib.executor.clmm.fusion` | `ks-lib-executor.clmm.fusion` |
|
||||||
| `kb-lib.executor.clmm.orca_whirlpool` | `ks-lib-executor.clmm.orca_whirlpool` |
|
| `kb-lib.executor.clmm.orca_whirlpool` | `ks-lib-executor.clmm.orca_whirlpool` |
|
||||||
| `kb-lib.executor.clmm.pancake_swap` | `ks-lib-executor.clmm.pancake_swap` |
|
| `kb-lib.executor.clmm.pancake_swap` | `ks-lib-executor.clmm.pancake_swap` |
|
||||||
| `kb-lib.executor.clmm.raydium` | `ks-lib-executor.clmm.raydium` |
|
| `kb-lib.executor.clmm.raydium` | `ks-lib-executor.clmm.raydium` |
|
||||||
| `kb-lib.executor.clmm.stabble` | `ks-lib-executor.clmm.stabble` |
|
| `kb-lib.executor.clmm.stabble` | `ks-lib-executor.clmm.stabble` |
|
||||||
| `kb-lib.executor.cpmm.raydium` | `ks-lib-executor.cpmm.raydium` |
|
| `kb-lib.executor.cpmm.raydium` | `ks-lib-executor.cpmm.raydium` |
|
||||||
| `kb-lib.executor.dlmm.meteora` | `ks-lib-executor.dlmm.meteora` |
|
| `kb-lib.executor.dlmm.meteora` | `ks-lib-executor.dlmm.meteora` |
|
||||||
| `kb-lib.executor.fees.bags_fee_share_v1` | `ks-lib-executor.fees.bags_fee_share_v1` |
|
| `kb-lib.executor.fees.bags_fee_share_v1` | `ks-lib-executor.fees.bags_fee_share_v1` |
|
||||||
| `kb-lib.executor.fees.bags_fee_share_v2` | `ks-lib-executor.fees.bags_fee_share_v2` |
|
| `kb-lib.executor.fees.bags_fee_share_v2` | `ks-lib-executor.fees.bags_fee_share_v2` |
|
||||||
| `kb-lib.executor.fees.pump_fees` | `ks-lib-executor.fees.pump_fees` |
|
| `kb-lib.executor.fees.pump_fees` | `ks-lib-executor.fees.pump_fees` |
|
||||||
| `kb-lib.executor.governance.metadao_bid_wall` | `ks-lib-executor.governance.metadao_bid_wall` |
|
| `kb-lib.executor.governance.metadao_bid_wall` | `ks-lib-executor.governance.metadao_bid_wall` |
|
||||||
| `kb-lib.executor.governance.metadao_futarchy` | `ks-lib-executor.governance.metadao_futarchy` |
|
| `kb-lib.executor.governance.metadao_futarchy` | `ks-lib-executor.governance.metadao_futarchy` |
|
||||||
| `kb-lib.executor.governance.squads_multisig` | `ks-lib-executor.governance.squads_multisig` |
|
| `kb-lib.executor.governance.squads_multisig` | `ks-lib-executor.governance.squads_multisig` |
|
||||||
| `kb-lib.executor.launchpad.boop_fun` | `ks-lib-executor.launchpad.boop_fun` |
|
| `kb-lib.executor.launchpad.boop_fun` | `ks-lib-executor.launchpad.boop_fun` |
|
||||||
| `kb-lib.executor.launchpad.metadao_ico` | `ks-lib-executor.launchpad.metadao_ico` |
|
| `kb-lib.executor.launchpad.metadao_ico` | `ks-lib-executor.launchpad.metadao_ico` |
|
||||||
| `kb-lib.executor.launchpad.meteora_dbc` | `ks-lib-executor.launchpad.meteora_dbc` |
|
| `kb-lib.executor.launchpad.meteora_dbc` | `ks-lib-executor.launchpad.meteora_dbc` |
|
||||||
| `kb-lib.executor.launchpad.moonit` | `ks-lib-executor.launchpad.moonit` |
|
| `kb-lib.executor.launchpad.moonit` | `ks-lib-executor.launchpad.moonit` |
|
||||||
| `kb-lib.executor.launchpad.orca_wavebreak` | `ks-lib-executor.launchpad.orca_wavebreak` |
|
| `kb-lib.executor.launchpad.orca_wavebreak` | `ks-lib-executor.launchpad.orca_wavebreak` |
|
||||||
| `kb-lib.executor.launchpad.printr` | `ks-lib-executor.launchpad.printr` |
|
| `kb-lib.executor.launchpad.printr` | `ks-lib-executor.launchpad.printr` |
|
||||||
| `kb-lib.executor.launchpad.pump_fun` | `ks-lib-executor.launchpad.pump_fun` |
|
| `kb-lib.executor.launchpad.pump_fun` | `ks-lib-executor.launchpad.pump_fun` |
|
||||||
| `kb-lib.executor.launchpad.pump_pumpup_ai` | `ks-lib-executor.launchpad.pump_pumpup_ai` |
|
| `kb-lib.executor.launchpad.pump_pumpup_ai` | `ks-lib-executor.launchpad.pump_pumpup_ai` |
|
||||||
| `kb-lib.executor.launchpad.raydium_launchlab` | `ks-lib-executor.launchpad.raydium_launchlab` |
|
| `kb-lib.executor.launchpad.raydium_launchlab` | `ks-lib-executor.launchpad.raydium_launchlab` |
|
||||||
| `kb-lib.executor.launchpad.virtuals` | `ks-lib-executor.launchpad.virtuals` |
|
| `kb-lib.executor.launchpad.virtuals` | `ks-lib-executor.launchpad.virtuals` |
|
||||||
| `kb-lib.executor.lending.clone` | `ks-lib-executor.lending.clone` |
|
| `kb-lib.executor.lending.clone` | `ks-lib-executor.lending.clone` |
|
||||||
| `kb-lib.executor.lending.jupiter_lend_borrow` | `ks-lib-executor.lending.jupiter_lend_borrow` |
|
| `kb-lib.executor.lending.jupiter_lend_borrow` | `ks-lib-executor.lending.jupiter_lend_borrow` |
|
||||||
| `kb-lib.executor.lending.jupiter_lend_earn` | `ks-lib-executor.lending.jupiter_lend_earn` |
|
| `kb-lib.executor.lending.jupiter_lend_earn` | `ks-lib-executor.lending.jupiter_lend_earn` |
|
||||||
| `kb-lib.executor.lending.jupiter_lend_flash_loan` | `ks-lib-executor.lending.jupiter_lend_flash_loan` |
|
| `kb-lib.executor.lending.jupiter_lend_flash_loan` | `ks-lib-executor.lending.jupiter_lend_flash_loan` |
|
||||||
| `kb-lib.executor.lending.jupiter_lend_liquidity` | `ks-lib-executor.lending.jupiter_lend_liquidity` |
|
| `kb-lib.executor.lending.jupiter_lend_liquidity` | `ks-lib-executor.lending.jupiter_lend_liquidity` |
|
||||||
| `kb-lib.executor.lending.kamino` | `ks-lib-executor.lending.kamino` |
|
| `kb-lib.executor.lending.kamino` | `ks-lib-executor.lending.kamino` |
|
||||||
| `kb-lib.executor.lending.marginfi_v2` | `ks-lib-executor.lending.marginfi_v2` |
|
| `kb-lib.executor.lending.marginfi_v2` | `ks-lib-executor.lending.marginfi_v2` |
|
||||||
| `kb-lib.executor.lock.raydium_lp` | `ks-lib-executor.lock.raydium_lp` |
|
| `kb-lib.executor.lock.raydium_lp` | `ks-lib-executor.lock.raydium_lp` |
|
||||||
| `kb-lib.executor.metadata.metaplex_token_metadata` | `ks-lib-executor.metadata.metaplex_token_metadata` |
|
| `kb-lib.executor.metadata.metaplex_token_metadata` | `ks-lib-executor.metadata.metaplex_token_metadata` |
|
||||||
| `kb-lib.executor.metadata.solana_program_metadata` | `ks-lib-executor.metadata.solana_program_metadata` |
|
| `kb-lib.executor.metadata.solana_program_metadata` | `ks-lib-executor.metadata.solana_program_metadata` |
|
||||||
| `kb-lib.executor.metadata.spl_name_service` | `ks-lib-executor.metadata.spl_name_service` |
|
| `kb-lib.executor.metadata.spl_name_service` | `ks-lib-executor.metadata.spl_name_service` |
|
||||||
| `kb-lib.executor.nft.metaplex_bubblegum` | `ks-lib-executor.nft.metaplex_bubblegum` |
|
| `kb-lib.executor.nft.metaplex_bubblegum` | `ks-lib-executor.nft.metaplex_bubblegum` |
|
||||||
| `kb-lib.executor.nft.tensor_cnft` | `ks-lib-executor.nft.tensor_cnft` |
|
| `kb-lib.executor.nft.tensor_cnft` | `ks-lib-executor.nft.tensor_cnft` |
|
||||||
| `kb-lib.executor.orderbook.jupiter_limit_order` | `ks-lib-executor.orderbook.jupiter_limit_order` |
|
| `kb-lib.executor.orderbook.jupiter_limit_order` | `ks-lib-executor.orderbook.jupiter_limit_order` |
|
||||||
| `kb-lib.executor.orderbook.jupiter_limit_order_v2` | `ks-lib-executor.orderbook.jupiter_limit_order_v2` |
|
| `kb-lib.executor.orderbook.jupiter_limit_order_v2` | `ks-lib-executor.orderbook.jupiter_limit_order_v2` |
|
||||||
| `kb-lib.executor.orderbook.openbook_v2` | `ks-lib-executor.orderbook.openbook_v2` |
|
| `kb-lib.executor.orderbook.openbook_v2` | `ks-lib-executor.orderbook.openbook_v2` |
|
||||||
| `kb-lib.executor.perpetuals.drift_v2` | `ks-lib-executor.perpetuals.drift_v2` |
|
| `kb-lib.executor.perpetuals.drift_v2` | `ks-lib-executor.perpetuals.drift_v2` |
|
||||||
| `kb-lib.executor.perpetuals.jupiter` | `ks-lib-executor.perpetuals.jupiter` |
|
| `kb-lib.executor.perpetuals.jupiter` | `ks-lib-executor.perpetuals.jupiter` |
|
||||||
| `kb-lib.executor.perpetuals.phoenix_eternal` | `ks-lib-executor.perpetuals.phoenix_eternal` |
|
| `kb-lib.executor.perpetuals.phoenix_eternal` | `ks-lib-executor.perpetuals.phoenix_eternal` |
|
||||||
| `kb-lib.executor.perpetuals.zeta` | `ks-lib-executor.perpetuals.zeta` |
|
| `kb-lib.executor.perpetuals.zeta` | `ks-lib-executor.perpetuals.zeta` |
|
||||||
| `kb-lib.executor.router.dflow_aggregator_v4` | `ks-lib-executor.router.dflow_aggregator_v4` |
|
| `kb-lib.executor.router.dflow_aggregator_v4` | `ks-lib-executor.router.dflow_aggregator_v4` |
|
||||||
| `kb-lib.executor.router.jupiter_aggregator_v4` | `ks-lib-executor.router.jupiter_aggregator_v4` |
|
| `kb-lib.executor.router.jupiter_aggregator_v4` | `ks-lib-executor.router.jupiter_aggregator_v4` |
|
||||||
| `kb-lib.executor.router.jupiter_aggregator_v6` | `ks-lib-executor.router.jupiter_aggregator_v6` |
|
| `kb-lib.executor.router.jupiter_aggregator_v6` | `ks-lib-executor.router.jupiter_aggregator_v6` |
|
||||||
| `kb-lib.executor.router.okx_labs_v1` | `ks-lib-executor.router.okx_labs_v1` |
|
| `kb-lib.executor.router.okx_labs_v1` | `ks-lib-executor.router.okx_labs_v1` |
|
||||||
| `kb-lib.executor.router.okx_labs_v2` | `ks-lib-executor.router.okx_labs_v2` |
|
| `kb-lib.executor.router.okx_labs_v2` | `ks-lib-executor.router.okx_labs_v2` |
|
||||||
| `kb-lib.executor.rwa.ondo_global_markets` | `ks-lib-executor.rwa.ondo_global_markets` |
|
| `kb-lib.executor.rwa.ondo_global_markets` | `ks-lib-executor.rwa.ondo_global_markets` |
|
||||||
| `kb-lib.executor.solana.core` | `ks-lib-executor.solana.core` |
|
| `kb-lib.executor.solana.core` | `ks-lib-executor.solana.core` |
|
||||||
| `kb-lib.executor.solana.transaction` | `ks-lib-executor.solana.transaction` |
|
| `kb-lib.executor.solana.transaction` | `ks-lib-executor.solana.transaction` |
|
||||||
| `kb-lib.executor.spl.account_compression` | `ks-lib-executor.spl.account_compression` |
|
| `kb-lib.executor.spl.account_compression` | `ks-lib-executor.spl.account_compression` |
|
||||||
| `kb-lib.executor.spl.associated_token_account` | `ks-lib-executor.spl.associated_token_account` |
|
| `kb-lib.executor.spl.associated_token_account` | `ks-lib-executor.spl.associated_token_account` |
|
||||||
| `kb-lib.executor.spl.elgamal_registry` | `ks-lib-executor.spl.elgamal_registry` |
|
| `kb-lib.executor.spl.elgamal_registry` | `ks-lib-executor.spl.elgamal_registry` |
|
||||||
| `kb-lib.executor.spl.memo` | `ks-lib-executor.spl.memo` |
|
| `kb-lib.executor.spl.memo` | `ks-lib-executor.spl.memo` |
|
||||||
| `kb-lib.executor.spl.noop` | `ks-lib-executor.spl.noop` |
|
| `kb-lib.executor.spl.noop` | `ks-lib-executor.spl.noop` |
|
||||||
| `kb-lib.executor.spl.single_pool` | `ks-lib-executor.spl.single_pool` |
|
| `kb-lib.executor.spl.single_pool` | `ks-lib-executor.spl.single_pool` |
|
||||||
| `kb-lib.executor.spl.stake_pool` | `ks-lib-executor.spl.stake_pool` |
|
| `kb-lib.executor.spl.stake_pool` | `ks-lib-executor.spl.stake_pool` |
|
||||||
| `kb-lib.executor.spl.token` | `ks-lib-executor.spl.token` |
|
| `kb-lib.executor.spl.token` | `ks-lib-executor.spl.token` |
|
||||||
| `kb-lib.executor.spl.token-2022` | `ks-lib-executor.spl.token-2022` |
|
| `kb-lib.executor.spl.token-2022` | `ks-lib-executor.spl.token-2022` |
|
||||||
| `kb-lib.executor.spl.token_2022` | `ks-lib-executor.spl.token_2022` |
|
| `kb-lib.executor.spl.token_2022` | `ks-lib-executor.spl.token_2022` |
|
||||||
| `kb-lib.executor.stable.swap_hylo_exchange` | `ks-lib-executor.stable.swap_hylo_exchange` |
|
| `kb-lib.executor.stable.swap_hylo_exchange` | `ks-lib-executor.stable.swap_hylo_exchange` |
|
||||||
| `kb-lib.executor.stable.swap_jupiter_stable` | `ks-lib-executor.stable.swap_jupiter_stable` |
|
| `kb-lib.executor.stable.swap_jupiter_stable` | `ks-lib-executor.stable.swap_jupiter_stable` |
|
||||||
| `kb-lib.executor.stable.swap_numeraire` | `ks-lib-executor.stable.swap_numeraire` |
|
| `kb-lib.executor.stable.swap_numeraire` | `ks-lib-executor.stable.swap_numeraire` |
|
||||||
| `kb-lib.executor.stable.swap_stabble` | `ks-lib-executor.stable.swap_stabble` |
|
| `kb-lib.executor.stable.swap_stabble` | `ks-lib-executor.stable.swap_stabble` |
|
||||||
| `kb-lib.executor.staking.jito_tip_distribution` | `ks-lib-executor.staking.jito_tip_distribution` |
|
| `kb-lib.executor.staking.jito_tip_distribution` | `ks-lib-executor.staking.jito_tip_distribution` |
|
||||||
| `kb-lib.executor.staking.kamino_farm` | `ks-lib-executor.staking.kamino_farm` |
|
| `kb-lib.executor.staking.kamino_farm` | `ks-lib-executor.staking.kamino_farm` |
|
||||||
| `kb-lib.executor.staking.marinade_finance` | `ks-lib-executor.staking.marinade_finance` |
|
| `kb-lib.executor.staking.marinade_finance` | `ks-lib-executor.staking.marinade_finance` |
|
||||||
| `kb-lib.executor.staking.solayer` | `ks-lib-executor.staking.solayer` |
|
| `kb-lib.executor.staking.solayer` | `ks-lib-executor.staking.solayer` |
|
||||||
| `kb-lib.executor.storage.solana_record` | `ks-lib-executor.storage.solana_record` |
|
| `kb-lib.executor.storage.solana_record` | `ks-lib-executor.storage.solana_record` |
|
||||||
| `kb-lib.executor.strategy.jupiter_dca` | `ks-lib-executor.strategy.jupiter_dca` |
|
| `kb-lib.executor.strategy.jupiter_dca` | `ks-lib-executor.strategy.jupiter_dca` |
|
||||||
| `kb-lib.executor.treasury.helium_treasury_management` | `ks-lib-executor.treasury.helium_treasury_management` |
|
| `kb-lib.executor.treasury.helium_treasury_management` | `ks-lib-executor.treasury.helium_treasury_management` |
|
||||||
| `kb-lib.executor.vault.carrot_defi` | `ks-lib-executor.vault.carrot_defi` |
|
| `kb-lib.executor.vault.carrot_defi` | `ks-lib-executor.vault.carrot_defi` |
|
||||||
| `kb-lib.executor.vault.hylo_stability_pool` | `ks-lib-executor.vault.hylo_stability_pool` |
|
| `kb-lib.executor.vault.hylo_stability_pool` | `ks-lib-executor.vault.hylo_stability_pool` |
|
||||||
| `kb-lib.executor.vault.kamino` | `ks-lib-executor.vault.kamino` |
|
| `kb-lib.executor.vault.kamino` | `ks-lib-executor.vault.kamino` |
|
||||||
| `kb-lib.executor.vault.kamino_v2` | `ks-lib-executor.vault.kamino_v2` |
|
| `kb-lib.executor.vault.kamino_v2` | `ks-lib-executor.vault.kamino_v2` |
|
||||||
| `kb-lib.executor.vault.kamino_yvaults` | `ks-lib-executor.vault.kamino_yvaults` |
|
| `kb-lib.executor.vault.kamino_yvaults` | `ks-lib-executor.vault.kamino_yvaults` |
|
||||||
| `kb-lib.executor.vault.meteora` | `ks-lib-executor.vault.meteora` |
|
| `kb-lib.executor.vault.meteora` | `ks-lib-executor.vault.meteora` |
|
||||||
| `kb-lib.executor.vesting.jupiter_lock` | `ks-lib-executor.vesting.jupiter_lock` |
|
| `kb-lib.executor.vesting.jupiter_lock` | `ks-lib-executor.vesting.jupiter_lock` |
|
||||||
| `kb-lib.executor.vesting.streamflow` | `ks-lib-executor.vesting.streamflow` |
|
| `kb-lib.executor.vesting.streamflow` | `ks-lib-executor.vesting.streamflow` |
|
||||||
| `kb-lib.executor.wallet.jupiter_apepro_smart_wallet` | `ks-lib-executor.wallet.jupiter_apepro_smart_wallet` |
|
| `kb-lib.executor.wallet.jupiter_apepro_smart_wallet` | `ks-lib-executor.wallet.jupiter_apepro_smart_wallet` |
|
||||||
| `kb-lib.executor.weighted.swap_stabble` | `ks-lib-executor.weighted.swap_stabble` |
|
| `kb-lib.executor.weighted.swap_stabble` | `ks-lib-executor.weighted.swap_stabble` |
|
||||||
| `kb-lib.materializer.admin` | `ks-lib-materializer.admin` |
|
| `kb-lib.materializer.admin` | `ks-lib-materializer.admin` |
|
||||||
| `kb-lib.materializer.bridge` | `ks-lib-materializer.bridge` |
|
| `kb-lib.materializer.bridge` | `ks-lib-materializer.bridge` |
|
||||||
| `kb-lib.materializer.compliance.audit` | `ks-lib-materializer.compliance.audit` |
|
| `kb-lib.materializer.compliance.audit` | `ks-lib-materializer.compliance.audit` |
|
||||||
| `kb-lib.materializer.fees` | `ks-lib-materializer.fees` |
|
| `kb-lib.materializer.fees` | `ks-lib-materializer.fees` |
|
||||||
| `kb-lib.materializer.governance` | `ks-lib-materializer.governance` |
|
| `kb-lib.materializer.governance` | `ks-lib-materializer.governance` |
|
||||||
| `kb-lib.materializer.lending` | `ks-lib-materializer.lending` |
|
| `kb-lib.materializer.lending` | `ks-lib-materializer.lending` |
|
||||||
| `kb-lib.materializer.lifecycle` | `ks-lib-materializer.lifecycle` |
|
| `kb-lib.materializer.lifecycle` | `ks-lib-materializer.lifecycle` |
|
||||||
| `kb-lib.materializer.liquidity` | `ks-lib-materializer.liquidity` |
|
| `kb-lib.materializer.liquidity` | `ks-lib-materializer.liquidity` |
|
||||||
| `kb-lib.materializer.metadata.metaplex_token_metadata` | `ks-lib-materializer.metadata.metaplex_token_metadata` |
|
| `kb-lib.materializer.metadata.metaplex_token_metadata` | `ks-lib-materializer.metadata.metaplex_token_metadata` |
|
||||||
| `kb-lib.materializer.metadata.solana_program_metadata` | `ks-lib-materializer.metadata.solana_program_metadata` |
|
| `kb-lib.materializer.metadata.solana_program_metadata` | `ks-lib-materializer.metadata.solana_program_metadata` |
|
||||||
| `kb-lib.materializer.metadata.token_2022` | `ks-lib-materializer.metadata.token_2022` |
|
| `kb-lib.materializer.metadata.token_2022` | `ks-lib-materializer.metadata.token_2022` |
|
||||||
| `kb-lib.materializer.nft` | `ks-lib-materializer.nft` |
|
| `kb-lib.materializer.nft` | `ks-lib-materializer.nft` |
|
||||||
| `kb-lib.materializer.oracle` | `ks-lib-materializer.oracle` |
|
| `kb-lib.materializer.oracle` | `ks-lib-materializer.oracle` |
|
||||||
| `kb-lib.materializer.orderbook` | `ks-lib-materializer.orderbook` |
|
| `kb-lib.materializer.orderbook` | `ks-lib-materializer.orderbook` |
|
||||||
| `kb-lib.materializer.perpetuals` | `ks-lib-materializer.perpetuals` |
|
| `kb-lib.materializer.perpetuals` | `ks-lib-materializer.perpetuals` |
|
||||||
| `kb-lib.materializer.pool.state` | `ks-lib-materializer.pool.state` |
|
| `kb-lib.materializer.pool.state` | `ks-lib-materializer.pool.state` |
|
||||||
| `kb-lib.materializer.rewards` | `ks-lib-materializer.rewards` |
|
| `kb-lib.materializer.rewards` | `ks-lib-materializer.rewards` |
|
||||||
| `kb-lib.materializer.risk` | `ks-lib-materializer.risk` |
|
| `kb-lib.materializer.risk` | `ks-lib-materializer.risk` |
|
||||||
| `kb-lib.materializer.routing` | `ks-lib-materializer.routing` |
|
| `kb-lib.materializer.routing` | `ks-lib-materializer.routing` |
|
||||||
| `kb-lib.materializer.staking` | `ks-lib-materializer.staking` |
|
| `kb-lib.materializer.staking` | `ks-lib-materializer.staking` |
|
||||||
| `kb-lib.materializer.token.accounts` | `ks-lib-materializer.token.accounts` |
|
| `kb-lib.materializer.token.accounts` | `ks-lib-materializer.token.accounts` |
|
||||||
| `kb-lib.materializer.token.metadata_risk` | `ks-lib-materializer.token.metadata_risk` |
|
| `kb-lib.materializer.token.metadata_risk` | `ks-lib-materializer.token.metadata_risk` |
|
||||||
| `kb-lib.materializer.trades` | `ks-lib-materializer.trades` |
|
| `kb-lib.materializer.trades` | `ks-lib-materializer.trades` |
|
||||||
| `kb-lib.materializer.transaction.annotations` | `ks-lib-materializer.transaction.annotations` |
|
| `kb-lib.materializer.transaction.annotations` | `ks-lib-materializer.transaction.annotations` |
|
||||||
| `kb-lib.materializer.vault` | `ks-lib-materializer.vault` |
|
| `kb-lib.materializer.vault` | `ks-lib-materializer.vault` |
|
||||||
|
|
||||||
## 7. Inventaire des variables d'environnement
|
## 7. Inventaire des variables d'environnement
|
||||||
|
|
||||||
@@ -446,13 +446,13 @@ Les anciennes fixtures `TOKEN_2022_*` et les alias opérateur déjà préfixés
|
|||||||
|
|
||||||
### 7.2 Mapping code/config/tests — 85 noms
|
### 7.2 Mapping code/config/tests — 85 noms
|
||||||
|
|
||||||
| Nom actuel | Nom cible | Classe |
|
| Nom actuel | Nom cible | Classe |
|
||||||
|---|---|---|
|
|------------------------------|-----------------------------------|----------------|
|
||||||
| `HELIUS_API_KEY` | `KS_SECRET_HELIUS_API_KEY` | `secret` |
|
| `HELIUS_API_KEY` | `KS_SECRET_HELIUS_API_KEY` | `secret` |
|
||||||
| `KB_CONFIG_PATH` | `KB_APP_DEMO_DESKTOP_CONFIG_PATH` | `internal` Bot |
|
| `KB_CONFIG_PATH` | `KB_APP_DEMO_DESKTOP_CONFIG_PATH` | `internal` Bot |
|
||||||
| `KB_CONFIG_TEST_MISSING` | `KS_CONFIG_TEST_MISSING` | `internal` |
|
| `KB_CONFIG_TEST_MISSING` | `KS_CONFIG_TEST_MISSING` | `internal` |
|
||||||
| `KB_DEVNET_AIRDROP_LAMPORTS` | `KS_DEVNET_AIRDROP_LAMPORTS` | `internal` |
|
| `KB_DEVNET_AIRDROP_LAMPORTS` | `KS_DEVNET_AIRDROP_LAMPORTS` | `internal` |
|
||||||
| `KB_DEVNET_CONFIG_PATH` | `KS_DEVNET_CONFIG_PATH` | `internal` |
|
| `KB_DEVNET_CONFIG_PATH` | `KS_DEVNET_CONFIG_PATH` | `internal` |
|
||||||
|
|
||||||
La cible `KB_APP_DEMO_DESKTOP_CONFIG_PATH` remplace la transition `KS_CONFIG_PATH` de `pre.004` : une composition appartient au binaire qui la charge, alors que les documents qu’elle référence restent possédés par les crates `ks-*`.
|
La cible `KB_APP_DEMO_DESKTOP_CONFIG_PATH` remplace la transition `KS_CONFIG_PATH` de `pre.004` : une composition appartient au binaire qui la charge, alors que les documents qu’elle référence restent possédés par les crates `ks-*`.
|
||||||
| `KB_DEVNET_EXECUTION_TEST` | `KS_DEVNET_EXECUTION_TEST` | `internal` |
|
| `KB_DEVNET_EXECUTION_TEST` | `KS_DEVNET_EXECUTION_TEST` | `internal` |
|
||||||
@@ -538,25 +538,25 @@ La cible `KB_APP_DEMO_DESKTOP_CONFIG_PATH` remplace la transition `KS_CONFIG_PAT
|
|||||||
|
|
||||||
### 7.3 Mapping guide opérateur Devnet — 17 noms
|
### 7.3 Mapping guide opérateur Devnet — 17 noms
|
||||||
|
|
||||||
| Nom actuel | Nom cible | Classe |
|
| Nom actuel | Nom cible | Classe |
|
||||||
|---|---|---|
|
|---------------------------------------|---------------------------------------|------------|
|
||||||
| `KB_CONFIRM_DEVNET_DATABASE_RESET` | `KS_CONFIRM_DEVNET_DATABASE_RESET` | `internal` |
|
| `KB_CONFIRM_DEVNET_DATABASE_RESET` | `KS_CONFIRM_DEVNET_DATABASE_RESET` | `internal` |
|
||||||
| `KB_DEVNET_CLASSIC_DESTINATION_ATA` | `KS_DEVNET_CLASSIC_DESTINATION_ATA` | `internal` |
|
| `KB_DEVNET_CLASSIC_DESTINATION_ATA` | `KS_DEVNET_CLASSIC_DESTINATION_ATA` | `internal` |
|
||||||
| `KB_DEVNET_CLASSIC_MINT` | `KS_DEVNET_CLASSIC_MINT` | `internal` |
|
| `KB_DEVNET_CLASSIC_MINT` | `KS_DEVNET_CLASSIC_MINT` | `internal` |
|
||||||
| `KB_DEVNET_CLASSIC_MINT_KEYPAIR` | `KS_DEVNET_CLASSIC_MINT_KEYPAIR` | `internal` |
|
| `KB_DEVNET_CLASSIC_MINT_KEYPAIR` | `KS_DEVNET_CLASSIC_MINT_KEYPAIR` | `internal` |
|
||||||
| `KB_DEVNET_CLASSIC_RECIPIENT` | `KS_DEVNET_CLASSIC_RECIPIENT` | `internal` |
|
| `KB_DEVNET_CLASSIC_RECIPIENT` | `KS_DEVNET_CLASSIC_RECIPIENT` | `internal` |
|
||||||
| `KB_DEVNET_CLASSIC_RECIPIENT_KEYPAIR` | `KS_DEVNET_CLASSIC_RECIPIENT_KEYPAIR` | `internal` |
|
| `KB_DEVNET_CLASSIC_RECIPIENT_KEYPAIR` | `KS_DEVNET_CLASSIC_RECIPIENT_KEYPAIR` | `internal` |
|
||||||
| `KB_DEVNET_CLASSIC_SOURCE_ATA` | `KS_DEVNET_CLASSIC_SOURCE_ATA` | `internal` |
|
| `KB_DEVNET_CLASSIC_SOURCE_ATA` | `KS_DEVNET_CLASSIC_SOURCE_ATA` | `internal` |
|
||||||
| `KB_DEVNET_RECIPIENT` | `KS_DEVNET_RECIPIENT` | `internal` |
|
| `KB_DEVNET_RECIPIENT` | `KS_DEVNET_RECIPIENT` | `internal` |
|
||||||
| `KB_DEVNET_SCENARIO` | `KS_DEVNET_SCENARIO` | `internal` |
|
| `KB_DEVNET_SCENARIO` | `KS_DEVNET_SCENARIO` | `internal` |
|
||||||
| `KB_DEVNET_SIGNATURE` | `KS_DEVNET_SIGNATURE` | `internal` |
|
| `KB_DEVNET_SIGNATURE` | `KS_DEVNET_SIGNATURE` | `internal` |
|
||||||
| `KB_DEVNET_TOKEN_2022_FIXTURE` | `KS_DEVNET_TOKEN_2022_FIXTURE` | `internal` |
|
| `KB_DEVNET_TOKEN_2022_FIXTURE` | `KS_DEVNET_TOKEN_2022_FIXTURE` | `internal` |
|
||||||
| `KB_DEVNET_TOKEN_2022_MINT` | `KS_PUBLIC_DEVNET_TOKEN_2022_MINT` | `public` |
|
| `KB_DEVNET_TOKEN_2022_MINT` | `KS_PUBLIC_DEVNET_TOKEN_2022_MINT` | `public` |
|
||||||
| `KB_DEVNET_TOKEN_2022_MINT_KEYPAIR` | `KS_DEVNET_TOKEN_2022_MINT_KEYPAIR` | `internal` |
|
| `KB_DEVNET_TOKEN_2022_MINT_KEYPAIR` | `KS_DEVNET_TOKEN_2022_MINT_KEYPAIR` | `internal` |
|
||||||
| `KB_DEVNET_VALIDATION_DIR` | `KS_DEVNET_VALIDATION_DIR` | `internal` |
|
| `KB_DEVNET_VALIDATION_DIR` | `KS_DEVNET_VALIDATION_DIR` | `internal` |
|
||||||
| `KB_DEVNET_WALLET_PUBKEY` | `KS_PUBLIC_DEVNET_WALLET_ADDRESS` | `public` |
|
| `KB_DEVNET_WALLET_PUBKEY` | `KS_PUBLIC_DEVNET_WALLET_ADDRESS` | `public` |
|
||||||
| `KB_SPL_TOKEN_2022_PROGRAM_ID` | `KS_PUBLIC_SPL_TOKEN_2022_PROGRAM_ID` | `public` |
|
| `KB_SPL_TOKEN_2022_PROGRAM_ID` | `KS_PUBLIC_SPL_TOKEN_2022_PROGRAM_ID` | `public` |
|
||||||
| `KB_SPL_TOKEN_PROGRAM_ID` | `KS_PUBLIC_SPL_TOKEN_PROGRAM_ID` | `public` |
|
| `KB_SPL_TOKEN_PROGRAM_ID` | `KS_PUBLIC_SPL_TOKEN_PROGRAM_ID` | `public` |
|
||||||
|
|
||||||
## 8. Décomposition des documents de configuration
|
## 8. Décomposition des documents de configuration
|
||||||
|
|
||||||
@@ -595,7 +595,7 @@ Le transport possède des classes WebSocket de defaults nommées. Chaque endpoin
|
|||||||
|
|
||||||
Lorsqu'une composition référence un profil, `ks-config` doit prouver son existence avant de construire le runtime. Lorsqu'aucune composition n'est fournie, les noms des `default_profile` n'ont pas besoin d'être identiques : chaque document est résolu indépendamment. La composition ne devient pas une seconde surface de paramètres : les overrides de champ restent dans le contrat spécialisé qui les possède, et les globals explicitement configurables utilisent leurs variables d'environnement dédiées.
|
Lorsqu'une composition référence un profil, `ks-config` doit prouver son existence avant de construire le runtime. Lorsqu'aucune composition n'est fournie, les noms des `default_profile` n'ont pas besoin d'être identiques : chaque document est résolu indépendamment. La composition ne devient pas une seconde surface de paramètres : les overrides de champ restent dans le contrat spécialisé qui les possède, et les globals explicitement configurables utilisent leurs variables d'environnement dédiées.
|
||||||
|
|
||||||
`AppConfig/ProfileConfig` demeure provisoirement un **contrat runtime résolu** pour préserver les consommateurs pendant la migration. Les champs applicatifs `app`/`demo` restent dans la composition exclusive du desktop pendant cette transition ; leur ownership Rust/public est traité avec les DTO applicatifs de `pre.008`, sans réintroduire un document généraliste monolithique.
|
`AppConfig/ProfileConfig` demeure provisoirement un **contrat runtime résolu backend-only** pour préserver les consommateurs pendant la migration. Depuis `pre.008`, il ne contient plus les champs propres au desktop, ne dérive plus `serde::Serialize`/`Debug` et ne traverse plus Tauri. La section `application` de la composition est opaque à `ks-config`; le desktop la valide avec son propre schéma sans réintroduire un document généraliste monolithique.
|
||||||
|
|
||||||
## 9. Source, runtime, public et diagnostic
|
## 9. Source, runtime, public et diagnostic
|
||||||
|
|
||||||
@@ -606,38 +606,34 @@ La configuration doit distinguer explicitement :
|
|||||||
3. **public** : DTO explicitement construit et strictement borné pour Tauri/TS-RS/UI ;
|
3. **public** : DTO explicitement construit et strictement borné pour Tauri/TS-RS/UI ;
|
||||||
4. **diagnostic** : surface explicitement demandée, pouvant montrer des valeurs `KS_*` internes non sensibles mais jamais une valeur `KS_SECRET_*`.
|
4. **diagnostic** : surface explicitement demandée, pouvant montrer des valeurs `KS_*` internes non sensibles mais jamais une valeur `KS_SECRET_*`.
|
||||||
|
|
||||||
### 9.1 Fuite actuelle à éliminer
|
### 9.1 Frontière appliquée en `pre.008`
|
||||||
|
|
||||||
`kb-app-demo-desktop/src/demo_config.rs` transporte actuellement dans `DemoConfigPayload` :
|
`kb-app-demo-desktop/src/demo_config.rs` ne transporte plus `AppConfig` ni `ProfileConfig`. Il construit explicitement :
|
||||||
|
|
||||||
```text
|
```text
|
||||||
AppConfig complet
|
runtime backend-only
|
||||||
ProfileConfig actif complet
|
-> DemoConfigPublicPayload
|
||||||
schema_json
|
-> DemoConfigDiagnosticPayload
|
||||||
```
|
```
|
||||||
|
|
||||||
La configuration est déjà résolue avant la construction du payload, puis le frontend affiche les objets via JsonViewer. Cette frontière permet donc à un secret résolu d'atteindre Tauri/UI.
|
La projection publique exclut URLs, DSN, chemins de stockage/wallet et politiques internes non destinées à l'UI. Le diagnostic borné ne transmet pour les valeurs sensibles que des états tels que `configured`/`missing`, plus les métadonnées internes explicitement autorisées.
|
||||||
|
|
||||||
La correction ne doit jamais suivre le modèle :
|
La correction interdit le modèle :
|
||||||
|
|
||||||
```text
|
```text
|
||||||
serialize(runtime_config) -> supprimer quelques champs -> exposer
|
serialize(runtime_config) -> supprimer quelques champs -> exposer
|
||||||
```
|
```
|
||||||
|
|
||||||
La seule direction admise est :
|
Les contrats source/runtime de `ks-config` susceptibles de contenir des secrets résolus ne dérivent ni `serde::Serialize` ni `Debug`, et les sérialiseurs publics historiques de `AppConfig` sont supprimés. La sensibilité des placeholders est classée selon `Secret > Internal > Public`; une chaîne composée contenant un placeholder `KS_SECRET_*`/`KB_SECRET_*` hérite de `Secret`.
|
||||||
|
|
||||||
```text
|
TS-RS est désormais une frontière applicative : `ks-config` et `ks-lib` ne dépendent plus de `ts-rs` et ne génèrent plus de bindings. `kb-app-demo-desktop` possède les DTO TS-RS nécessaires à ses commandes Tauri.
|
||||||
runtime_config -> construction explicite d'un PublicConfig / ConfigDiagnostics
|
|
||||||
```
|
|
||||||
|
|
||||||
Les types contenant des secrets ne doivent pas être exportés en TS-RS simplement parce qu'ils sont sérialisables côté backend.
|
|
||||||
|
|
||||||
## 10. Tests de caractérisation avant et pendant migration
|
## 10. Tests de caractérisation avant et pendant migration
|
||||||
|
|
||||||
Avant chaque changement structurel correspondant, conserver ou ajouter des tests qui vérifient :
|
Avant chaque changement structurel correspondant, conserver ou ajouter des tests qui vérifient :
|
||||||
|
|
||||||
- la topologie des dix crates et leurs dépendances attendues ;
|
- la topologie des dix crates et leurs dépendances attendues ;
|
||||||
- les 13 tests d'API externe et leurs imports par crate root ;
|
- les 14 tests d'API externe et leurs imports par crate root ;
|
||||||
- l'inventaire exact des identités runtime ;
|
- l'inventaire exact des identités runtime ;
|
||||||
- l'absence de `kb-*` / `kb_*` résiduel dans les dix crates après leur prerelease de renommage, hors exceptions explicitement listées ;
|
- l'absence de `kb-*` / `kb_*` résiduel dans les dix crates après leur prerelease de renommage, hors exceptions explicitement listées ;
|
||||||
- le maintien de `khadhroony-bot3` comme nom racine ;
|
- le maintien de `khadhroony-bot3` comme nom racine ;
|
||||||
@@ -730,13 +726,14 @@ Le split partagé est considéré terminé après cette prerelease. Les champs a
|
|||||||
|
|
||||||
### `0.5.1-pre.008` — surfaces publiques sûres, TS-RS et camouflage
|
### `0.5.1-pre.008` — surfaces publiques sûres, TS-RS et camouflage
|
||||||
|
|
||||||
- séparer types source/runtime/public/diagnostic ;
|
- **implémenté** : `AppConfig/ProfileConfig` et les documents source/runtime sensibles restent backend-only, sans `serde::Serialize` ni `Debug` ;
|
||||||
- déplacer les DTO réellement destinés à Tauri/TypeScript vers `kb-app-demo-desktop` ou des wrappers applicatifs dédiés ;
|
- **implémenté** : le fragment `application` devient opaque pour `ks-config` et est validé par le schéma possédé par `kb-app-demo-desktop` ;
|
||||||
- supprimer les dérivations/export TS-RS de `ks-config` qui n'ont aucun consommateur frontend générique et auditer les 100 exports de `ks-lib` au cas par cas ;
|
- **implémenté** : `DemoConfigPayload` remplace la configuration résolue complète par des DTO public/diagnostic construits champ par champ ;
|
||||||
- propager la classification secret/public/internal lors de la résolution des placeholders et valeurs composées ;
|
- **implémenté** : URLs RPC/WS, DSN PostgreSQL et chemins sensibles ne traversent pas le payload configuration ; les diagnostics n'exposent que des états bornés ;
|
||||||
- retirer `AppConfig`/`ProfileConfig` résolus du payload Tauri public ;
|
- **implémenté** : classification `Secret > Internal > Public` des variables et chaînes composées, avec canaris de non-divulgation et erreurs de validation qui n'échoent plus les valeurs rejetées ;
|
||||||
- borner les DTO TS-RS et diagnostics ;
|
- **implémenté** : suppression de `ts-rs` de `ks-config` et `ks-lib`, suppression de leurs dérivations/export et de leurs bindings générés historiques ;
|
||||||
- valider qu'aucun secret ne traverse logs/UI/erreurs/sérialisation.
|
- **implémenté** : audit workspace empêchant la réintroduction de TS-RS dans `ks-*` et de `Serialize`/`Debug` sur les contrats de configuration sensibles sans décision explicite ;
|
||||||
|
- **implémenté** : test d'API externe de la classification/camouflage et canaris desktop empêchant la fuite de secrets dans les projections Tauri.
|
||||||
|
|
||||||
### `0.5.1-pre.009` — clôture
|
### `0.5.1-pre.009` — clôture
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<!-- file: docs/rules/RULES_SPECIFIC_KHADHROONY.md -->
|
<!-- file: docs/rules/RULES_SPECIFIC_KHADHROONY.md -->
|
||||||
<!-- version: 18 -->
|
<!-- version: 21 -->
|
||||||
|
|
||||||
# Règles spécifiques à `khadhroony-bot3`
|
# Règles spécifiques à `khadhroony-bot3`
|
||||||
|
|
||||||
@@ -12,7 +12,7 @@ Toute divergence avec une règle générale doit être explicitement documentée
|
|||||||
- Tous les noms de fichiers et de répertoires doivent être écrits en anglais.
|
- Tous les noms de fichiers et de répertoires doivent être écrits en anglais.
|
||||||
- Les noms de fichiers et de répertoires ne doivent contenir aucun accent, espace ou caractère spécial inutile.
|
- Les noms de fichiers et de répertoires ne doivent contenir aucun accent, espace ou caractère spécial inutile.
|
||||||
- Les noms internes doivent utiliser le format `snake_case` lorsque c'est applicable.
|
- Les noms internes doivent utiliser le format `snake_case` lorsque c'est applicable.
|
||||||
- Les packages Rust utilisent le préfixe `kb-` ; leur identifiant Rust correspondant utilise automatiquement `kb_`.
|
- Les bibliothèques généralistes Khadhroony Solana utilisent le préfixe Cargo `ks-` et l’identifiant Rust `ks_`; les applications et futures crates réellement propres au domaine Bot utilisent `kb-` / `kb_`.
|
||||||
- Les décodeurs, matérialisateurs et exécuteurs sont des modules de `ks-lib`, pas des crates séparées.
|
- Les décodeurs, matérialisateurs et exécuteurs sont des modules de `ks-lib`, pas des crates séparées.
|
||||||
- Le crate de journalisation s'appelle `ks-logging`.
|
- Le crate de journalisation s'appelle `ks-logging`.
|
||||||
- Les réexports sont regroupés par visibilité : le bloc `pub use` précède le bloc séparé `pub(crate) use`, sans ligne vide interne à un bloc ; leur ordre naturel doit rester compatible avec `cargo fmt`.
|
- Les réexports sont regroupés par visibilité : le bloc `pub use` précède le bloc séparé `pub(crate) use`, sans ligne vide interne à un bloc ; leur ordre naturel doit rester compatible avec `cargo fmt`.
|
||||||
@@ -26,6 +26,8 @@ Toute divergence avec une règle générale doit être explicitement documentée
|
|||||||
- Les types Rust exportés vers TypeScript doivent utiliser des noms stables et explicites.
|
- Les types Rust exportés vers TypeScript doivent utiliser des noms stables et explicites.
|
||||||
- Les bindings générés doivent être produits dans un dossier dédié, généralement `../frontend/ts/bindings` ou `#[ts(export, export_to = "../frontend/ts/bindings/MyStruct.ts")]`.
|
- Les bindings générés doivent être produits dans un dossier dédié, généralement `../frontend/ts/bindings` ou `#[ts(export, export_to = "../frontend/ts/bindings/MyStruct.ts")]`.
|
||||||
- Les types purement internes au backend ne doivent pas être exportés vers TypeScript par défaut.
|
- Les types purement internes au backend ne doivent pas être exportés vers TypeScript par défaut.
|
||||||
|
- Dans l’état courant, les crates généralistes `ks-*` ne possèdent ni dépendance `ts-rs`, ni dérivation/export TS-RS, ni dossier de bindings générés. Une exception future exige un contrat TypeScript générique indépendant de Tauri, explicitement documenté et ajouté à l’audit workspace.
|
||||||
|
- Les types source/runtime de `ks-config` susceptibles de contenir des secrets ou valeurs internes ne dérivent ni `serde::Serialize` ni `Debug`. Une surface publique ou diagnostic est construite champ par champ dans l’application propriétaire ; il est interdit de sérialiser un runtime complet puis de le redacter a posteriori.
|
||||||
- Corriger le type Rust/TS-rs source puis régénérer les bindings ; ne pas considérer une modification manuelle isolée d’un fichier généré comme un correctif durable.
|
- Corriger le type Rust/TS-rs source puis régénérer les bindings ; ne pas considérer une modification manuelle isolée d’un fichier généré comme un correctif durable.
|
||||||
- `kb-app-demo-desktop/src/tauri.rs` contient les attributs `#[tauri::command]`, l’enregistrement des commandes et des wrappers privés minces ; la logique complète doit vivre dans le module fonctionnel correspondant sous une fonction `pub(crate)` testable.
|
- `kb-app-demo-desktop/src/tauri.rs` contient les attributs `#[tauri::command]`, l’enregistrement des commandes et des wrappers privés minces ; la logique complète doit vivre dans le module fonctionnel correspondant sous une fonction `pub(crate)` testable.
|
||||||
- Un wrapper Tauri ne doit effectuer que l’adaptation des handles/states/arguments, l’appel de la fonction de module et le retour du résultat ; toute validation métier, orchestration ou construction de payload doit rester hors de `tauri.rs`.
|
- Un wrapper Tauri ne doit effectuer que l’adaptation des handles/states/arguments, l’appel de la fonction de module et le retour du résultat ; toute validation métier, orchestration ou construction de payload doit rester hors de `tauri.rs`.
|
||||||
@@ -247,8 +249,8 @@ Aucun renommage massif de modules n'est autorisé sans étape de contrôle dédi
|
|||||||
- Les endpoints WebSocket doivent sélectionner une classe de defaults nommée ; leurs timeouts, capacités et politique `auto_reconnect` peuvent être remplacés explicitement au niveau de l'endpoint.
|
- Les endpoints WebSocket doivent sélectionner une classe de defaults nommée ; leurs timeouts, capacités et politique `auto_reconnect` peuvent être remplacés explicitement au niveau de l'endpoint.
|
||||||
- Les autorisations `*_send_enabled` appartiennent à la politique d'exécution, pas au contrat d'identité/stockage wallet.
|
- Les autorisations `*_send_enabled` appartiennent à la politique d'exécution, pas au contrat d'identité/stockage wallet.
|
||||||
- Les schémas JSON actifs sont conservés exclusivement sous `config/schemas/`. Les documents source spécialisés possèdent chacun leur schéma ; `resolved.app.config.schema.json` décrit uniquement le contrat runtime transitoire reconstruit par `ks-config`.
|
- Les schémas JSON actifs sont conservés exclusivement sous `config/schemas/`. Les documents source spécialisés possèdent chacun leur schéma ; `resolved.app.config.schema.json` décrit uniquement le contrat runtime transitoire reconstruit par `ks-config`.
|
||||||
- Les exemples conformes restent sous `config/` avec un nom distinct des fichiers runtime. Les fixtures d'un contrat runtime résolu appartiennent à `test-fixtures/` et ne doivent pas être chargées en production.
|
- Les exemples conformes résident exclusivement sous `config/exemples/` avec un nom distinct des fichiers runtime. Les fixtures d'un contrat runtime résolu appartiennent à `test-fixtures/` et ne doivent pas être chargées en production.
|
||||||
- Les fichiers historiques `config/app.config.json`, `config/example.app.config.json`, `config/schemas/app.config.schema.json`, `config/example.config.json`, `config/schema.config.json` et `config/ks-pipeline-demo-scenarios.default.config.json` sont interdits dans l'état courant.
|
- Les fichiers historiques `config/app.config.json`, `config/example.app.config.json`, `config/schemas/app.config.schema.json`, `config/example.config.json`, les fichiers `config/example.*.config.json` hors `config/exemples/`, `config/schema.config.json` et `config/ks-pipeline-demo-scenarios.default.config.json` sont interdits dans l'état courant.
|
||||||
- Le chemin de composition desktop peut être remplacé par `KB_APP_DEMO_DESKTOP_CONFIG_PATH`. `KS_DEVNET_CONFIG_PATH` est uniquement un override facultatif vers une composition explicite pour les scénarios Devnet ; sans cet override, les scénarios utilisent les defaults partagés. `KS_LOGGING_CONFIG_PATH` reste un override explicite du document logging.
|
- Le chemin de composition desktop peut être remplacé par `KB_APP_DEMO_DESKTOP_CONFIG_PATH`. `KS_DEVNET_CONFIG_PATH` est uniquement un override facultatif vers une composition explicite pour les scénarios Devnet ; sans cet override, les scénarios utilisent les defaults partagés. `KS_LOGGING_CONFIG_PATH` reste un override explicite du document logging.
|
||||||
- Les fichiers JSON de configuration ne doivent pas contenir de commentaires.
|
- Les fichiers JSON de configuration ne doivent pas contenir de commentaires.
|
||||||
- Les secrets ne doivent pas être écrits en clair dans le dépôt.
|
- Les secrets ne doivent pas être écrits en clair dans le dépôt.
|
||||||
@@ -256,7 +258,13 @@ Aucun renommage massif de modules n'est autorisé sans étape de contrôle dédi
|
|||||||
- Les variables possédées par les composants généralistes `ks-*` utilisent obligatoirement `KS_SECRET_*`, `KS_PUBLIC_*` ou `KS_*` ; les variables réellement spécifiques à `kb-app-demo-desktop` ou à de futures crates `kb-*` utilisent `KB_SECRET_*`, `KB_PUBLIC_*` ou `KB_*`.
|
- Les variables possédées par les composants généralistes `ks-*` utilisent obligatoirement `KS_SECRET_*`, `KS_PUBLIC_*` ou `KS_*` ; les variables réellement spécifiques à `kb-app-demo-desktop` ou à de futures crates `kb-*` utilisent `KB_SECRET_*`, `KB_PUBLIC_*` ou `KB_*`.
|
||||||
- Le namespace est déterminé par le propriétaire fonctionnel du contrat et non par son consommateur.
|
- Le namespace est déterminé par le propriétaire fonctionnel du contrat et non par son consommateur.
|
||||||
- Les sous-préfixes `SECRET` sont toujours non exposables ; les sous-préfixes `PUBLIC` ne sont exposables que par une surface explicitement autorisée ; les autres variables du domaine sont internes.
|
- Les sous-préfixes `SECRET` sont toujours non exposables ; les sous-préfixes `PUBLIC` ne sont exposables que par une surface explicitement autorisée ; les autres variables du domaine sont internes.
|
||||||
- Les bindings TS-RS sont prioritairement une frontière d'application Tauri. Une crate `ks-*` ne conserve une dérivation/export TypeScript que si le type constitue un contrat externe générique explicitement justifié ; sinon l'application définit un DTO/wrapper dédié.
|
- La sensibilité d’une valeur composée suit `Secret > Internal > Public` : une URL, un DSN ou toute autre chaîne incorporant un placeholder `KS_SECRET_*`/`KB_SECRET_*` hérite de la sensibilité `Secret`, quel que soit le nom du champ final.
|
||||||
|
- Une valeur `Secret` ne doit jamais apparaître en clair dans une sérialisation, un `Debug`, une erreur, un log, un diagnostic, un payload Tauri ou l’UI. Une valeur interne n’apparaît que dans un diagnostic explicitement borné et sémantiquement autorisé.
|
||||||
|
- La section `application` d’une composition est opaque pour `ks-config`; le binaire propriétaire définit et valide son propre schéma sous `config/schemas/` avant usage.
|
||||||
|
- Les bindings TS-RS sont une frontière d'application Tauri. Une crate `ks-*` ne conserve une dérivation/export TypeScript que si le type constitue un contrat externe générique explicitement justifié et audité ; sinon l'application définit un DTO/wrapper dédié.
|
||||||
|
- Une commande Tauri ne retourne jamais directement un contrat `ks-*` susceptible de contenir des valeurs runtime ; elle retourne un DTO appartenant à l’application et construit explicitement la projection autorisée.
|
||||||
|
- Les snapshots/runtime transport contenant une URL résolue restent backend-only : ils ne sont pas sérialisables directement, leur `Debug` est sanitisé, les DTO Tauri ne contiennent pas `endpoint_url`, et les erreurs/logs de transport ne recopient ni corps HTTP non-success ni message JSON-RPC distant susceptible de réinjecter un credential.
|
||||||
|
- Les chemins dérivés du stockage wallet sont internes ; un payload fonctionnel Tauri ne transporte pas un chemin de fixture. Seule une surface de diagnostic explicitement bornée peut exposer un chemin interne autorisé.
|
||||||
|
|
||||||
## Ordre de développement cible
|
## Ordre de développement cible
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,20 @@
|
|||||||
<!-- file: kb-app-demo-desktop/CHANGELOG.md -->
|
<!-- file: kb-app-demo-desktop/CHANGELOG.md -->
|
||||||
<!-- version: 47 -->
|
<!-- version: 52 -->
|
||||||
|
|
||||||
# CHANGELOG — kb-app-demo-desktop
|
# CHANGELOG — kb-app-demo-desktop
|
||||||
|
|
||||||
|
## `0.5.1-pre.008`
|
||||||
|
|
||||||
|
- Fix: remplace les snapshots `ks-onchain-transport` retournés directement par les commandes Tauri HTTP/WS par des DTO desktop sanitisés, fait supprimer l’URL des snapshots backend et supprime `endpointUrl` des payloads d’exécution/statut et ajoute des canaris empêchant toute URL résolue de traverser le frontend. Supprime également le chemin local du fixture Token-2022 des payloads fonctionnels et des erreurs affichées.
|
||||||
|
|
||||||
|
- Fix: use the crate-root DTO façades inside the configuration projection itself so required `pub(crate)` re-exports are not dead imports.
|
||||||
|
- Fix: remove the unused desktop application-schema getter; validation continues to use the embedded schema directly.
|
||||||
|
|
||||||
|
- remplace l'exposition Tauri de `AppConfig/ProfileConfig` résolus par une projection publique typée et un diagnostic borné construits champ par champ ;
|
||||||
|
- n'expose plus les URLs RPC/WebSocket, DSN PostgreSQL, chemins SQLite/wallet ni aucune valeur secrète ; les diagnostics correspondants transmettent seulement des états `configured`/`missing` et des paramètres non sensibles explicitement retenus ;
|
||||||
|
- devient propriétaire du fragment `application` de sa composition et le valide avec `config/schemas/kb-app-demo-desktop.application.config.schema.json` ;
|
||||||
|
- conserve TS-RS uniquement à la frontière applicative et ajoute des canaris garantissant que les valeurs sensibles injectées dans le runtime ne traversent pas les payloads configuration.
|
||||||
|
|
||||||
## `0.5.1-pre.007`
|
## `0.5.1-pre.007`
|
||||||
|
|
||||||
- consomme les nouveaux documents store/wallet/execution via la composition desktop ;
|
- consomme les nouveaux documents store/wallet/execution via la composition desktop ;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<!-- file: kb-app-demo-desktop/README.md -->
|
<!-- file: kb-app-demo-desktop/README.md -->
|
||||||
<!-- version: 14 -->
|
<!-- version: 15 -->
|
||||||
|
|
||||||
# kb-app-demo-desktop
|
# kb-app-demo-desktop
|
||||||
|
|
||||||
@@ -21,6 +21,10 @@ Les commandes Tauri sont des adaptateurs minces. La logique réutilisable appart
|
|||||||
|
|
||||||
Les campagnes Devnet/Testnet réutilisables appartiennent à `ks-pipeline-demo-scenarios`. Le desktop conserve leurs adaptateurs UI/Tauri, la sélection opérateur, la progression, les payloads TS-RS et la présentation ; `0.5.4` doit retirer les orchestrations réutilisables qui subsistent encore localement.
|
Les campagnes Devnet/Testnet réutilisables appartiennent à `ks-pipeline-demo-scenarios`. Le desktop conserve leurs adaptateurs UI/Tauri, la sélection opérateur, la progression, les payloads TS-RS et la présentation ; `0.5.4` doit retirer les orchestrations réutilisables qui subsistent encore localement.
|
||||||
|
|
||||||
|
Depuis `0.5.1-pre.008`, TS-RS appartient à cette frontière applicative : `ks-config` et `ks-lib` ne génèrent plus de bindings TypeScript. Lorsqu'un type généraliste doit être présenté au frontend, le desktop construit un DTO/wrapper dédié.
|
||||||
|
|
||||||
|
La fenêtre Configuration ne reçoit plus `ks_config::AppConfig` ou `ProfileConfig`. Elle reçoit une projection publique typée et un diagnostic borné construits champ par champ. Les URLs, DSN et chemins sensibles ne traversent pas Tauri ; le diagnostic n'expose que leur état `configured`/`missing`.
|
||||||
|
|
||||||
## Exécution Metaplex Token Metadata
|
## Exécution Metaplex Token Metadata
|
||||||
|
|
||||||
Le panneau conserve les scénarios synthétiques pour inspecter les contrats, mais son parcours Devnet principal expose désormais 11 campagnes qualifiées de `pre.013` et appelle directement leurs runners spécialisés de `ks-pipeline-demo-scenarios`. Les cinq variantes `Create -> Mint`, collection, Print/Burn, lifecycle pNFT et escrow soumettent uniquement les opérations autorisées ; Maintenance et Use conservent les opérations `unavailable` dans des probes simulation-only. Le desktop ne reconstruit pas les builders ; il conserve encore une partie du dispatch, des critères de complétion et de la projection de preuves, à centraliser en `0.5.4` lorsque cette logique est réutilisable.
|
Le panneau conserve les scénarios synthétiques pour inspecter les contrats, mais son parcours Devnet principal expose désormais 11 campagnes qualifiées de `pre.013` et appelle directement leurs runners spécialisés de `ks-pipeline-demo-scenarios`. Les cinq variantes `Create -> Mint`, collection, Print/Burn, lifecycle pNFT et escrow soumettent uniquement les opérations autorisées ; Maintenance et Use conservent les opérations `unavailable` dans des probes simulation-only. Le desktop ne reconstruit pas les builders ; il conserve encore une partie du dispatch, des critères de complétion et de la projection de preuves, à centraliser en `0.5.4` lorsque cette logique est réutilisable.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<!-- file: kb-app-demo-desktop/frontend/demo_config.html -->
|
<!-- file: kb-app-demo-desktop/frontend/demo_config.html -->
|
||||||
<!-- version: 5 -->
|
<!-- version: 6 -->
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="fr">
|
<html lang="fr">
|
||||||
|
|
||||||
@@ -46,7 +46,7 @@
|
|||||||
<div class="col-12 col-xl-6">
|
<div class="col-12 col-xl-6">
|
||||||
<div class="card shadow-sm border-0 h-100">
|
<div class="card shadow-sm border-0 h-100">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<h2 class="h5 card-title mb-3">Configuration active</h2>
|
<h2 class="h5 card-title mb-3">Configuration publique</h2>
|
||||||
<div id="activeProfileJson" class="app-config-box app-json-viewer mb-0">Chargement...</div>
|
<div id="activeProfileJson" class="app-config-box app-json-viewer mb-0">Chargement...</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -55,7 +55,7 @@
|
|||||||
<div class="col-12 col-xl-6">
|
<div class="col-12 col-xl-6">
|
||||||
<div class="card shadow-sm border-0 h-100">
|
<div class="card shadow-sm border-0 h-100">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<h2 class="h5 card-title mb-3">Configuration complète</h2>
|
<h2 class="h5 card-title mb-3">Diagnostic borné</h2>
|
||||||
<div id="fullConfigJson" class="app-config-box app-json-viewer mb-0">Chargement...</div>
|
<div id="fullConfigJson" class="app-config-box app-json-viewer mb-0">Chargement...</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -64,7 +64,7 @@
|
|||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<div class="card shadow-sm border-0">
|
<div class="card shadow-sm border-0">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<h2 class="h5 card-title mb-3">Schéma JSON embarqué</h2>
|
<h2 class="h5 card-title mb-3">Schéma JSON de composition</h2>
|
||||||
<div id="schemaJson" class="app-config-box app-json-viewer mb-0">Chargement...</div>
|
<div id="schemaJson" class="app-config-box app-json-viewer mb-0">Chargement...</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// file: kb-app-demo-desktop/frontend/ts/demo_config.ts
|
// file: kb-app-demo-desktop/frontend/ts/demo_config.ts
|
||||||
// version: 6
|
// version: 7
|
||||||
|
|
||||||
import * as bootstrap from "bootstrap";
|
import * as bootstrap from "bootstrap";
|
||||||
import "simplebar";
|
import "simplebar";
|
||||||
@@ -55,12 +55,12 @@ function parseSchemaJson(schemaJson: string): unknown {
|
|||||||
async function loadDemoConfig(): Promise<void> {
|
async function loadDemoConfig(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
const payload = await invoke<DemoConfigPayload>("load_demo_config");
|
const payload = await invoke<DemoConfigPayload>("load_demo_config");
|
||||||
setText("#configPath", payload.config_path);
|
setText("#configPath", payload.diagnostic_config.sources.find(source => source.category === "composition")?.path ?? "non disponible");
|
||||||
setText("#activeProfileName", payload.active_profile_name);
|
setText("#activeProfileName", payload.active_profile_name);
|
||||||
setText("#activeEnvironment", payload.environment);
|
setText("#activeEnvironment", payload.environment);
|
||||||
renderJsonViewer("#activeProfileJson", payload.active_profile);
|
renderJsonViewer("#activeProfileJson", payload.public_config);
|
||||||
renderJsonViewer("#fullConfigJson", payload.app_config);
|
renderJsonViewer("#fullConfigJson", payload.diagnostic_config);
|
||||||
renderJsonViewer("#schemaJson", parseSchemaJson(payload.schema_json));
|
renderJsonViewer("#schemaJson", parseSchemaJson(payload.composition_schema_json));
|
||||||
} catch (caughtError) {
|
} catch (caughtError) {
|
||||||
const message = caughtError instanceof Error ? caughtError.message : String(caughtError);
|
const message = caughtError instanceof Error ? caughtError.message : String(caughtError);
|
||||||
setText("#activeProfileJson", `Erreur pendant le chargement de la configuration : ${message}`);
|
setText("#activeProfileJson", `Erreur pendant le chargement de la configuration : ${message}`);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// file: kb-app-demo-desktop/frontend/ts/demo_execution_spl.ts
|
// file: kb-app-demo-desktop/frontend/ts/demo_execution_spl.ts
|
||||||
// version: 9
|
// version: 10
|
||||||
|
|
||||||
import * as bootstrap from "bootstrap";
|
import * as bootstrap from "bootstrap";
|
||||||
import "simplebar";
|
import "simplebar";
|
||||||
@@ -698,7 +698,7 @@ async function loadToken2022Fixture(): Promise<void> {
|
|||||||
profileName: element<HTMLSelectElement>("#executionProfileSelect").value,
|
profileName: element<HTMLSelectElement>("#executionProfileSelect").value,
|
||||||
});
|
});
|
||||||
applyToken2022Fixture();
|
applyToken2022Fixture();
|
||||||
element<HTMLElement>("#token_2022FixtureHelp").textContent = `Fixture: ${token_2022Fixture.fixturePath} — program=${token_2022Fixture.programId}`;
|
element<HTMLElement>("#token_2022FixtureHelp").textContent = `Fixture Token-2022 chargée — program=${token_2022Fixture.programId}`;
|
||||||
appendLog({
|
appendLog({
|
||||||
timestamp: new Date().toISOString(),
|
timestamp: new Date().toISOString(),
|
||||||
level: "info",
|
level: "info",
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// file: kb-app-demo-desktop/frontend/ts/demo_http.ts
|
// file: kb-app-demo-desktop/frontend/ts/demo_http.ts
|
||||||
// version: 7
|
// version: 9
|
||||||
|
|
||||||
import * as bootstrap from "bootstrap";
|
import * as bootstrap from "bootstrap";
|
||||||
import "simplebar";
|
import "simplebar";
|
||||||
@@ -7,6 +7,7 @@ import ResizeObserver from "resize-observer-polyfill";
|
|||||||
import { invoke } from "@tauri-apps/api/core";
|
import { invoke } from "@tauri-apps/api/core";
|
||||||
import { frontendDebug, frontendError, installFrontendConsoleBridge } from "./frontend_log.ts";
|
import { frontendDebug, frontendError, installFrontendConsoleBridge } from "./frontend_log.ts";
|
||||||
import { renderJsonViewer } from "./json_viewer.ts";
|
import { renderJsonViewer } from "./json_viewer.ts";
|
||||||
|
import type { DemoHttpEndpointPayload } from "./bindings/kb_app_demo_desktop/demo_http/DemoHttpEndpointPayload.ts";
|
||||||
import type { DemoHttpExecutionPayload } from "./bindings/kb_app_demo_desktop/demo_http/DemoHttpExecutionPayload.ts";
|
import type { DemoHttpExecutionPayload } from "./bindings/kb_app_demo_desktop/demo_http/DemoHttpExecutionPayload.ts";
|
||||||
import type { DemoHttpMethodOption } from "./bindings/kb_app_demo_desktop/demo_http/DemoHttpMethodOption.ts";
|
import type { DemoHttpMethodOption } from "./bindings/kb_app_demo_desktop/demo_http/DemoHttpMethodOption.ts";
|
||||||
import type { DemoHttpOptionsPayload } from "./bindings/kb_app_demo_desktop/demo_http/DemoHttpOptionsPayload.ts";
|
import type { DemoHttpOptionsPayload } from "./bindings/kb_app_demo_desktop/demo_http/DemoHttpOptionsPayload.ts";
|
||||||
@@ -96,7 +97,6 @@ function formatHttpExecutionPayload(payload: DemoHttpExecutionPayload): unknown
|
|||||||
return {
|
return {
|
||||||
endpointName: payload.endpointName,
|
endpointName: payload.endpointName,
|
||||||
provider: payload.provider,
|
provider: payload.provider,
|
||||||
endpointUrl: payload.endpointUrl,
|
|
||||||
role: payload.role,
|
role: payload.role,
|
||||||
method: payload.method,
|
method: payload.method,
|
||||||
requestKind: payload.requestKind,
|
requestKind: payload.requestKind,
|
||||||
@@ -124,7 +124,7 @@ async function refreshHttpOptions(): Promise<void> {
|
|||||||
|
|
||||||
async function refreshHttpPool(): Promise<void> {
|
async function refreshHttpPool(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
const snapshots = await invoke("demo_http_list_pool_clients");
|
const snapshots = await invoke<DemoHttpEndpointPayload[]>("demo_http_list_pool_clients");
|
||||||
renderJsonViewer("#httpPoolOutput", snapshots);
|
renderJsonViewer("#httpPoolOutput", snapshots);
|
||||||
} catch (caughtError) {
|
} catch (caughtError) {
|
||||||
const message = caughtError instanceof Error ? caughtError.message : String(caughtError);
|
const message = caughtError instanceof Error ? caughtError.message : String(caughtError);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// file: kb-app-demo-desktop/frontend/ts/demo_ws.ts
|
// file: kb-app-demo-desktop/frontend/ts/demo_ws.ts
|
||||||
// version: 8
|
// version: 10
|
||||||
|
|
||||||
import * as bootstrap from "bootstrap";
|
import * as bootstrap from "bootstrap";
|
||||||
import "simplebar";
|
import "simplebar";
|
||||||
@@ -8,6 +8,7 @@ import {invoke} from "@tauri-apps/api/core";
|
|||||||
import {listen} from "@tauri-apps/api/event";
|
import {listen} from "@tauri-apps/api/event";
|
||||||
import {frontendDebug, frontendError, installFrontendConsoleBridge} from "./frontend_log.ts";
|
import {frontendDebug, frontendError, installFrontendConsoleBridge} from "./frontend_log.ts";
|
||||||
import {renderJsonViewer} from "./json_viewer.ts";
|
import {renderJsonViewer} from "./json_viewer.ts";
|
||||||
|
import type {DemoWsEndpointPayload} from "./bindings/kb_app_demo_desktop/demo_ws/DemoWsEndpointPayload.ts";
|
||||||
import type {DemoWsExecutionPayload} from "./bindings/kb_app_demo_desktop/demo_ws/DemoWsExecutionPayload.ts";
|
import type {DemoWsExecutionPayload} from "./bindings/kb_app_demo_desktop/demo_ws/DemoWsExecutionPayload.ts";
|
||||||
import type {DemoWsMessagePayload} from "./bindings/kb_app_demo_desktop/demo_ws/DemoWsMessagePayload.ts";
|
import type {DemoWsMessagePayload} from "./bindings/kb_app_demo_desktop/demo_ws/DemoWsMessagePayload.ts";
|
||||||
import type {DemoWsMethodOption} from "./bindings/kb_app_demo_desktop/demo_ws/DemoWsMethodOption.ts";
|
import type {DemoWsMethodOption} from "./bindings/kb_app_demo_desktop/demo_ws/DemoWsMethodOption.ts";
|
||||||
@@ -177,7 +178,6 @@ function formatWsExecutionPayload(payload: DemoWsExecutionPayload): string {
|
|||||||
const header = {
|
const header = {
|
||||||
endpointName: payload.endpointName,
|
endpointName: payload.endpointName,
|
||||||
provider: payload.provider,
|
provider: payload.provider,
|
||||||
endpointUrl: payload.endpointUrl,
|
|
||||||
role: payload.role,
|
role: payload.role,
|
||||||
method: payload.method,
|
method: payload.method,
|
||||||
requestKind: payload.requestKind,
|
requestKind: payload.requestKind,
|
||||||
@@ -214,7 +214,7 @@ async function refreshWsOptions(): Promise<void> {
|
|||||||
|
|
||||||
async function refreshWsPool(): Promise<void> {
|
async function refreshWsPool(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
const snapshots = await invoke("demo_ws_list_pool_clients");
|
const snapshots = await invoke<DemoWsEndpointPayload[]>("demo_ws_list_pool_clients");
|
||||||
renderJsonViewer("#wsPoolOutput", snapshots);
|
renderJsonViewer("#wsPoolOutput", snapshots);
|
||||||
} catch (caughtError) {
|
} catch (caughtError) {
|
||||||
const message = caughtError instanceof Error ? caughtError.message : String(caughtError);
|
const message = caughtError instanceof Error ? caughtError.message : String(caughtError);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// file: kb-app-demo-desktop/src/app_state.rs
|
// file: kb-app-demo-desktop/src/app_state.rs
|
||||||
// version: 15
|
// version: 16
|
||||||
|
|
||||||
//! Shared Tauri application state and startup initialization.
|
//! Shared Tauri application state and startup initialization.
|
||||||
|
|
||||||
@@ -7,6 +7,12 @@
|
|||||||
pub(crate) struct AppState {
|
pub(crate) struct AppState {
|
||||||
config_path: std::string::String,
|
config_path: std::string::String,
|
||||||
logging_config_path: std::string::String,
|
logging_config_path: std::string::String,
|
||||||
|
transport_config_path: std::string::String,
|
||||||
|
listeners_config_path: std::string::String,
|
||||||
|
store_config_path: std::string::String,
|
||||||
|
wallet_config_path: std::string::String,
|
||||||
|
execution_config_path: std::string::String,
|
||||||
|
desktop_config: crate::DesktopApplicationConfig,
|
||||||
app_config: ks_config::AppConfig,
|
app_config: ks_config::AppConfig,
|
||||||
active_profile: ks_config::ProfileConfig,
|
active_profile: ks_config::ProfileConfig,
|
||||||
logging_guard: std::sync::Mutex<ks_logging::LoggingGuard>,
|
logging_guard: std::sync::Mutex<ks_logging::LoggingGuard>,
|
||||||
@@ -44,8 +50,17 @@ impl crate::AppState {
|
|||||||
std::result::Result::Ok(profile) => profile.clone(),
|
std::result::Result::Ok(profile) => profile.clone(),
|
||||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||||
};
|
};
|
||||||
|
let desktop_config = match crate::desktop_application_config(&composition_profile) {
|
||||||
|
std::result::Result::Ok(config) => config,
|
||||||
|
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||||
|
};
|
||||||
let logging_config_path =
|
let logging_config_path =
|
||||||
resolve_logging_config_path(&workspace_root, &composed.logging_path);
|
resolve_logging_config_path(&workspace_root, &composed.logging_path);
|
||||||
|
let transport_config_path = composed.transport_path.display().to_string();
|
||||||
|
let listeners_config_path = composed.listeners_path.display().to_string();
|
||||||
|
let store_config_path = composed.store_path.display().to_string();
|
||||||
|
let wallet_config_path = composed.wallet_path.display().to_string();
|
||||||
|
let execution_config_path = composed.execution_path.display().to_string();
|
||||||
let app_config = composed.app_config;
|
let app_config = composed.app_config;
|
||||||
let active_profile = match ks_config::active_profile(&app_config) {
|
let active_profile = match ks_config::active_profile(&app_config) {
|
||||||
std::result::Result::Ok(profile) => profile.clone(),
|
std::result::Result::Ok(profile) => profile.clone(),
|
||||||
@@ -79,6 +94,12 @@ impl crate::AppState {
|
|||||||
return std::result::Result::Ok(crate::AppState {
|
return std::result::Result::Ok(crate::AppState {
|
||||||
config_path: config_path.display().to_string(),
|
config_path: config_path.display().to_string(),
|
||||||
logging_config_path: logging_config_path.display().to_string(),
|
logging_config_path: logging_config_path.display().to_string(),
|
||||||
|
transport_config_path,
|
||||||
|
listeners_config_path,
|
||||||
|
store_config_path,
|
||||||
|
wallet_config_path,
|
||||||
|
execution_config_path,
|
||||||
|
desktop_config,
|
||||||
app_config,
|
app_config,
|
||||||
active_profile,
|
active_profile,
|
||||||
logging_guard: std::sync::Mutex::new(logging_guard),
|
logging_guard: std::sync::Mutex::new(logging_guard),
|
||||||
@@ -108,6 +129,36 @@ impl crate::AppState {
|
|||||||
return self.logging_config_path.as_str();
|
return self.logging_config_path.as_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the path used to load the transport configuration file.
|
||||||
|
pub(crate) fn transport_config_path(&self) -> &str {
|
||||||
|
return self.transport_config_path.as_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the path used to load the listeners configuration file.
|
||||||
|
pub(crate) fn listeners_config_path(&self) -> &str {
|
||||||
|
return self.listeners_config_path.as_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the path used to load the store configuration file.
|
||||||
|
pub(crate) fn store_config_path(&self) -> &str {
|
||||||
|
return self.store_config_path.as_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the path used to load the wallet configuration file.
|
||||||
|
pub(crate) fn wallet_config_path(&self) -> &str {
|
||||||
|
return self.wallet_config_path.as_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the path used to load the execution configuration file.
|
||||||
|
pub(crate) fn execution_config_path(&self) -> &str {
|
||||||
|
return self.execution_config_path.as_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns desktop-owned settings selected from the active composition profile.
|
||||||
|
pub(crate) fn desktop_config(&self) -> &crate::DesktopApplicationConfig {
|
||||||
|
return &self.desktop_config;
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the complete parsed application configuration.
|
/// Returns the complete parsed application configuration.
|
||||||
pub(crate) fn app_config(&self) -> &ks_config::AppConfig {
|
pub(crate) fn app_config(&self) -> &ks_config::AppConfig {
|
||||||
return &self.app_config;
|
return &self.app_config;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// file: kb-app-demo-desktop/src/demo_config.rs
|
// file: kb-app-demo-desktop/src/demo_config.rs
|
||||||
// version: 3
|
// version: 5
|
||||||
|
|
||||||
//! Configuration demo payload and state projection.
|
//! Configuration demo payloads with explicit public and bounded diagnostic projections.
|
||||||
|
|
||||||
use ts_rs::TS; // rust-rules: derive-import
|
use ts_rs::TS; // rust-rules: derive-import
|
||||||
|
|
||||||
@@ -12,29 +12,432 @@ use ts_rs::TS; // rust-rules: derive-import
|
|||||||
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_config/DemoConfigPayload.ts"
|
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_config/DemoConfigPayload.ts"
|
||||||
)]
|
)]
|
||||||
pub(crate) struct DemoConfigPayload {
|
pub(crate) struct DemoConfigPayload {
|
||||||
/// Path used to load the configuration file.
|
/// Active composition profile name.
|
||||||
pub(crate) config_path: std::string::String,
|
|
||||||
/// Active profile name.
|
|
||||||
pub(crate) active_profile_name: std::string::String,
|
pub(crate) active_profile_name: std::string::String,
|
||||||
/// Active profile environment.
|
/// Desktop-owned environment label.
|
||||||
pub(crate) environment: std::string::String,
|
pub(crate) environment: std::string::String,
|
||||||
/// Entire parsed configuration.
|
/// Explicit public configuration projection.
|
||||||
pub(crate) app_config: ks_config::AppConfig,
|
pub(crate) public_config: crate::DemoConfigPublicPayload,
|
||||||
/// Active profile configuration.
|
/// Explicit bounded diagnostic projection.
|
||||||
pub(crate) active_profile: ks_config::ProfileConfig,
|
pub(crate) diagnostic_config: crate::DemoConfigDiagnosticPayload,
|
||||||
/// Embedded JSON Schema text used during loading.
|
/// Generic binary-composition JSON Schema text.
|
||||||
pub(crate) schema_json: std::string::String,
|
pub(crate) composition_schema_json: std::string::String,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Public desktop configuration projection containing no secret or internal paths.
|
||||||
|
#[derive(Clone, Debug, serde::Serialize, TS)]
|
||||||
|
#[ts(
|
||||||
|
export,
|
||||||
|
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_config/DemoConfigPublicPayload.ts"
|
||||||
|
)]
|
||||||
|
pub(crate) struct DemoConfigPublicPayload {
|
||||||
|
/// Desktop application identity.
|
||||||
|
pub(crate) application_name: std::string::String,
|
||||||
|
/// Desktop environment label.
|
||||||
|
pub(crate) environment: std::string::String,
|
||||||
|
/// Active composed profile.
|
||||||
|
pub(crate) profile_name: std::string::String,
|
||||||
|
/// Public HTTP endpoint identities without URLs or credentials.
|
||||||
|
pub(crate) http_endpoints: std::vec::Vec<crate::DemoConfigPublicEndpointPayload>,
|
||||||
|
/// Public WebSocket endpoint identities without URLs or credentials.
|
||||||
|
pub(crate) ws_endpoints: std::vec::Vec<crate::DemoConfigPublicEndpointPayload>,
|
||||||
|
/// Listener summary without account-specific filters.
|
||||||
|
pub(crate) listeners: crate::DemoConfigPublicListenersPayload,
|
||||||
|
/// Wallet cluster only; wallet paths and aliases remain diagnostic/internal.
|
||||||
|
pub(crate) wallet_cluster: std::string::String,
|
||||||
|
/// Desktop-owned demo feature flags.
|
||||||
|
pub(crate) demo: crate::DemoConfigPublicDemoPayload,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Public endpoint identity with no URL or authentication material.
|
||||||
|
#[derive(Clone, Debug, serde::Serialize, TS)]
|
||||||
|
#[ts(
|
||||||
|
export,
|
||||||
|
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_config/DemoConfigPublicEndpointPayload.ts"
|
||||||
|
)]
|
||||||
|
pub(crate) struct DemoConfigPublicEndpointPayload {
|
||||||
|
/// Endpoint code.
|
||||||
|
pub(crate) name: std::string::String,
|
||||||
|
/// Whether the endpoint is enabled.
|
||||||
|
pub(crate) enabled: bool,
|
||||||
|
/// Provider code.
|
||||||
|
pub(crate) provider: std::string::String,
|
||||||
|
/// Cluster code.
|
||||||
|
pub(crate) cluster: std::string::String,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Public listener summary.
|
||||||
|
#[derive(Clone, Debug, serde::Serialize, TS)]
|
||||||
|
#[ts(
|
||||||
|
export,
|
||||||
|
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_config/DemoConfigPublicListenersPayload.ts"
|
||||||
|
)]
|
||||||
|
pub(crate) struct DemoConfigPublicListenersPayload {
|
||||||
|
/// Whether listener creation is enabled.
|
||||||
|
pub(crate) enabled: bool,
|
||||||
|
/// Default commitment used by subscriptions.
|
||||||
|
pub(crate) default_commitment: std::string::String,
|
||||||
|
/// Number of log listener declarations.
|
||||||
|
pub(crate) log_listener_count: u32,
|
||||||
|
/// Number of program listener declarations.
|
||||||
|
pub(crate) program_listener_count: u32,
|
||||||
|
/// Number of account listener declarations.
|
||||||
|
pub(crate) account_listener_count: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Public desktop demo feature flags.
|
||||||
|
#[derive(Clone, Debug, serde::Serialize, TS)]
|
||||||
|
#[ts(
|
||||||
|
export,
|
||||||
|
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_config/DemoConfigPublicDemoPayload.ts"
|
||||||
|
)]
|
||||||
|
pub(crate) struct DemoConfigPublicDemoPayload {
|
||||||
|
/// Enables live demo pages.
|
||||||
|
pub(crate) live_demo_enabled: bool,
|
||||||
|
/// Enables trading demo pages.
|
||||||
|
pub(crate) trading_demo_enabled: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Bounded diagnostic projection containing internal configuration metadata but no secret values.
|
||||||
|
#[derive(Clone, Debug, serde::Serialize, TS)]
|
||||||
|
#[ts(
|
||||||
|
export,
|
||||||
|
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_config/DemoConfigDiagnosticPayload.ts"
|
||||||
|
)]
|
||||||
|
pub(crate) struct DemoConfigDiagnosticPayload {
|
||||||
|
/// Filesystem sources selected by the active binary composition.
|
||||||
|
pub(crate) sources: std::vec::Vec<crate::DemoConfigSourceDiagnosticPayload>,
|
||||||
|
/// Endpoint runtime settings without endpoint URLs.
|
||||||
|
pub(crate) endpoints: std::vec::Vec<crate::DemoConfigEndpointDiagnosticPayload>,
|
||||||
|
/// Store diagnostics without database URLs or filesystem paths.
|
||||||
|
pub(crate) store: crate::DemoConfigStoreDiagnosticPayload,
|
||||||
|
/// Wallet diagnostics without wallet filesystem paths or key material.
|
||||||
|
pub(crate) wallet: crate::DemoConfigWalletDiagnosticPayload,
|
||||||
|
/// Execution-policy diagnostics.
|
||||||
|
pub(crate) execution: crate::DemoConfigExecutionDiagnosticPayload,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// One selected configuration source exposed only through the explicit diagnostic surface.
|
||||||
|
#[derive(Clone, Debug, serde::Serialize, TS)]
|
||||||
|
#[ts(
|
||||||
|
export,
|
||||||
|
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_config/DemoConfigSourceDiagnosticPayload.ts"
|
||||||
|
)]
|
||||||
|
pub(crate) struct DemoConfigSourceDiagnosticPayload {
|
||||||
|
/// Source category.
|
||||||
|
pub(crate) category: std::string::String,
|
||||||
|
/// Resolved filesystem path.
|
||||||
|
pub(crate) path: std::string::String,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Endpoint diagnostic without URL content.
|
||||||
|
#[derive(Clone, Debug, serde::Serialize, TS)]
|
||||||
|
#[ts(
|
||||||
|
export,
|
||||||
|
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_config/DemoConfigEndpointDiagnosticPayload.ts"
|
||||||
|
)]
|
||||||
|
pub(crate) struct DemoConfigEndpointDiagnosticPayload {
|
||||||
|
/// Transport kind, either `http` or `ws`.
|
||||||
|
pub(crate) kind: std::string::String,
|
||||||
|
/// Endpoint code.
|
||||||
|
pub(crate) name: std::string::String,
|
||||||
|
/// Whether the endpoint is enabled.
|
||||||
|
pub(crate) enabled: bool,
|
||||||
|
/// Provider code.
|
||||||
|
pub(crate) provider: std::string::String,
|
||||||
|
/// Cluster code.
|
||||||
|
pub(crate) cluster: std::string::String,
|
||||||
|
/// URL state marker; the URL itself is never serialized.
|
||||||
|
pub(crate) url_state: std::string::String,
|
||||||
|
/// Connection timeout in milliseconds.
|
||||||
|
#[ts(type = "number")]
|
||||||
|
pub(crate) connect_timeout_ms: u64,
|
||||||
|
/// Request timeout in milliseconds.
|
||||||
|
#[ts(type = "number")]
|
||||||
|
pub(crate) request_timeout_ms: u64,
|
||||||
|
/// Optional unsubscribe timeout in milliseconds for WebSocket endpoints.
|
||||||
|
#[ts(type = "number | null")]
|
||||||
|
pub(crate) unsubscribe_timeout_ms: std::option::Option<u64>,
|
||||||
|
/// Optional reconnect policy for WebSocket endpoints.
|
||||||
|
pub(crate) auto_reconnect: std::option::Option<bool>,
|
||||||
|
/// Number of configured endpoint roles.
|
||||||
|
pub(crate) role_count: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Store diagnostic projection without DSN or SQLite path content.
|
||||||
|
#[derive(Clone, Debug, serde::Serialize, TS)]
|
||||||
|
#[ts(
|
||||||
|
export,
|
||||||
|
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_config/DemoConfigStoreDiagnosticPayload.ts"
|
||||||
|
)]
|
||||||
|
pub(crate) struct DemoConfigStoreDiagnosticPayload {
|
||||||
|
/// Whether persistence is enabled.
|
||||||
|
pub(crate) enabled: bool,
|
||||||
|
/// Selected store backend.
|
||||||
|
pub(crate) backend: std::string::String,
|
||||||
|
/// Whether a PostgreSQL URL is configured.
|
||||||
|
pub(crate) postgres_url_state: std::string::String,
|
||||||
|
/// PostgreSQL connection pool ceiling.
|
||||||
|
pub(crate) postgres_max_connections: u32,
|
||||||
|
/// PostgreSQL connection timeout in milliseconds.
|
||||||
|
#[ts(type = "number")]
|
||||||
|
pub(crate) postgres_connect_timeout_ms: u64,
|
||||||
|
/// Whether PostgreSQL schema initialization is enabled.
|
||||||
|
pub(crate) postgres_auto_initialize_schema: bool,
|
||||||
|
/// Whether a SQLite path is configured.
|
||||||
|
pub(crate) sqlite_path_state: std::string::String,
|
||||||
|
/// SQLite connection pool ceiling.
|
||||||
|
pub(crate) sqlite_max_connections: u32,
|
||||||
|
/// Whether SQLite schema initialization is enabled.
|
||||||
|
pub(crate) sqlite_auto_initialize_schema: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Wallet diagnostic projection without paths or secret key material.
|
||||||
|
#[derive(Clone, Debug, serde::Serialize, TS)]
|
||||||
|
#[ts(
|
||||||
|
export,
|
||||||
|
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_config/DemoConfigWalletDiagnosticPayload.ts"
|
||||||
|
)]
|
||||||
|
pub(crate) struct DemoConfigWalletDiagnosticPayload {
|
||||||
|
/// Whether a wallet directory is configured.
|
||||||
|
pub(crate) wallet_directory_state: std::string::String,
|
||||||
|
/// Wallet cluster.
|
||||||
|
pub(crate) cluster: std::string::String,
|
||||||
|
/// Whether the managed temporary wallet is enabled.
|
||||||
|
pub(crate) temporary_wallet_enabled: bool,
|
||||||
|
/// Temporary wallet alias, which is internal but not secret.
|
||||||
|
pub(crate) temporary_wallet_alias: std::string::String,
|
||||||
|
/// Whether the managed temporary wallet persists between restarts.
|
||||||
|
pub(crate) temporary_wallet_persist: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Execution-policy diagnostic projection.
|
||||||
|
#[derive(Clone, Debug, serde::Serialize, TS)]
|
||||||
|
#[ts(
|
||||||
|
export,
|
||||||
|
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_config/DemoConfigExecutionDiagnosticPayload.ts"
|
||||||
|
)]
|
||||||
|
pub(crate) struct DemoConfigExecutionDiagnosticPayload {
|
||||||
|
/// Enables local-validator sends.
|
||||||
|
pub(crate) localnet_send_enabled: bool,
|
||||||
|
/// Enables Devnet sends.
|
||||||
|
pub(crate) devnet_send_enabled: bool,
|
||||||
|
/// Enables Testnet sends.
|
||||||
|
pub(crate) testnet_send_enabled: bool,
|
||||||
|
/// Enables Mainnet sends.
|
||||||
|
pub(crate) mainnet_send_enabled: bool,
|
||||||
|
/// Default dry-run policy.
|
||||||
|
pub(crate) dry_run_default: bool,
|
||||||
|
/// Requires simulation before send.
|
||||||
|
pub(crate) require_simulation: bool,
|
||||||
|
/// Requires explicit operator confirmation.
|
||||||
|
pub(crate) require_operator_confirmation: bool,
|
||||||
|
/// Maximum local-validator spend in lamports.
|
||||||
|
#[ts(type = "number")]
|
||||||
|
pub(crate) localnet_max_spend_lamports: u64,
|
||||||
|
/// Maximum Devnet spend in lamports.
|
||||||
|
#[ts(type = "number")]
|
||||||
|
pub(crate) devnet_max_spend_lamports: u64,
|
||||||
|
/// Maximum Testnet spend in lamports.
|
||||||
|
#[ts(type = "number")]
|
||||||
|
pub(crate) testnet_max_spend_lamports: u64,
|
||||||
|
/// Maximum Mainnet spend in lamports.
|
||||||
|
#[ts(type = "number")]
|
||||||
|
pub(crate) mainnet_max_spend_lamports: u64,
|
||||||
|
/// Maximum fee in lamports.
|
||||||
|
#[ts(type = "number")]
|
||||||
|
pub(crate) max_fee_lamports: u64,
|
||||||
|
/// Maximum compute-unit price in micro-lamports.
|
||||||
|
#[ts(type = "number")]
|
||||||
|
pub(crate) max_compute_unit_price_micro_lamports: u64,
|
||||||
|
/// Maximum recent-blockhash age in slots.
|
||||||
|
#[ts(type = "number")]
|
||||||
|
pub(crate) recent_blockhash_max_age_slots: u64,
|
||||||
|
/// Maximum send retries.
|
||||||
|
pub(crate) send_max_retries: u32,
|
||||||
|
/// Confirmation poll interval in milliseconds.
|
||||||
|
#[ts(type = "number")]
|
||||||
|
pub(crate) confirmation_poll_interval_ms: u64,
|
||||||
|
/// Maximum confirmation poll attempts.
|
||||||
|
pub(crate) confirmation_max_attempts: u32,
|
||||||
|
/// Maximum Devnet faucet airdrop in lamports.
|
||||||
|
#[ts(type = "number")]
|
||||||
|
pub(crate) devnet_airdrop_max_lamports: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Builds the configuration payload from shared application state.
|
/// Builds the configuration payload from shared application state.
|
||||||
pub(crate) fn demo_config_payload(state: &crate::AppState) -> crate::DemoConfigPayload {
|
pub(crate) fn demo_config_payload(state: &crate::AppState) -> crate::DemoConfigPayload {
|
||||||
|
let active_profile = state.active_profile();
|
||||||
|
let desktop = state.desktop_config();
|
||||||
return crate::DemoConfigPayload {
|
return crate::DemoConfigPayload {
|
||||||
config_path: state.config_path().to_owned(),
|
active_profile_name: active_profile.name.clone(),
|
||||||
active_profile_name: state.active_profile().name.clone(),
|
environment: desktop.environment.clone(),
|
||||||
environment: state.active_profile().app.environment.clone(),
|
public_config: public_config_payload(active_profile, desktop),
|
||||||
app_config: state.app_config().clone(),
|
diagnostic_config: diagnostic_config_payload(state),
|
||||||
active_profile: state.active_profile().clone(),
|
composition_schema_json: ks_config::composition_json_schema_text().to_owned(),
|
||||||
schema_json: ks_config::config_json_schema_text().to_owned(),
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn public_config_payload(
|
||||||
|
profile: &ks_config::ProfileConfig,
|
||||||
|
desktop: &crate::DesktopApplicationConfig,
|
||||||
|
) -> DemoConfigPublicPayload {
|
||||||
|
let http_endpoints = profile
|
||||||
|
.solana
|
||||||
|
.http_endpoints
|
||||||
|
.iter()
|
||||||
|
.map(|endpoint| {
|
||||||
|
return DemoConfigPublicEndpointPayload {
|
||||||
|
name: endpoint.name.clone(),
|
||||||
|
enabled: endpoint.enabled,
|
||||||
|
provider: endpoint.provider.clone(),
|
||||||
|
cluster: endpoint.cluster.clone(),
|
||||||
|
};
|
||||||
|
})
|
||||||
|
.collect::<std::vec::Vec<DemoConfigPublicEndpointPayload>>();
|
||||||
|
let ws_endpoints = profile
|
||||||
|
.solana
|
||||||
|
.ws_endpoints
|
||||||
|
.iter()
|
||||||
|
.map(|endpoint| {
|
||||||
|
return DemoConfigPublicEndpointPayload {
|
||||||
|
name: endpoint.name.clone(),
|
||||||
|
enabled: endpoint.enabled,
|
||||||
|
provider: endpoint.provider.clone(),
|
||||||
|
cluster: endpoint.cluster.clone(),
|
||||||
|
};
|
||||||
|
})
|
||||||
|
.collect::<std::vec::Vec<DemoConfigPublicEndpointPayload>>();
|
||||||
|
return DemoConfigPublicPayload {
|
||||||
|
application_name: desktop.name.clone(),
|
||||||
|
environment: desktop.environment.clone(),
|
||||||
|
profile_name: profile.name.clone(),
|
||||||
|
http_endpoints,
|
||||||
|
ws_endpoints,
|
||||||
|
listeners: DemoConfigPublicListenersPayload {
|
||||||
|
enabled: profile.solana.listeners.enabled,
|
||||||
|
default_commitment: profile.solana.listeners.default_commitment.clone(),
|
||||||
|
log_listener_count: bounded_len(profile.solana.listeners.log_listeners.len()),
|
||||||
|
program_listener_count: bounded_len(profile.solana.listeners.program_listeners.len()),
|
||||||
|
account_listener_count: bounded_len(profile.solana.listeners.account_listeners.len()),
|
||||||
|
},
|
||||||
|
wallet_cluster: profile.wallet.cluster.clone(),
|
||||||
|
demo: DemoConfigPublicDemoPayload {
|
||||||
|
live_demo_enabled: desktop.demo.live_demo_enabled,
|
||||||
|
trading_demo_enabled: desktop.demo.trading_demo_enabled,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn diagnostic_config_payload(state: &crate::AppState) -> DemoConfigDiagnosticPayload {
|
||||||
|
let profile = state.active_profile();
|
||||||
|
let mut endpoints = std::vec::Vec::<DemoConfigEndpointDiagnosticPayload>::new();
|
||||||
|
for endpoint in &profile.solana.http_endpoints {
|
||||||
|
endpoints.push(DemoConfigEndpointDiagnosticPayload {
|
||||||
|
kind: "http".to_string(),
|
||||||
|
name: endpoint.name.clone(),
|
||||||
|
enabled: endpoint.enabled,
|
||||||
|
provider: endpoint.provider.clone(),
|
||||||
|
cluster: endpoint.cluster.clone(),
|
||||||
|
url_state: configured_state(endpoint.url.as_str()),
|
||||||
|
connect_timeout_ms: endpoint.connect_timeout_ms,
|
||||||
|
request_timeout_ms: endpoint.request_timeout_ms,
|
||||||
|
unsubscribe_timeout_ms: std::option::Option::None,
|
||||||
|
auto_reconnect: std::option::Option::None,
|
||||||
|
role_count: bounded_len(endpoint.roles.len()),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
for endpoint in &profile.solana.ws_endpoints {
|
||||||
|
endpoints.push(DemoConfigEndpointDiagnosticPayload {
|
||||||
|
kind: "ws".to_string(),
|
||||||
|
name: endpoint.name.clone(),
|
||||||
|
enabled: endpoint.enabled,
|
||||||
|
provider: endpoint.provider.clone(),
|
||||||
|
cluster: endpoint.cluster.clone(),
|
||||||
|
url_state: configured_state(endpoint.url.as_str()),
|
||||||
|
connect_timeout_ms: endpoint.connect_timeout_ms,
|
||||||
|
request_timeout_ms: endpoint.request_timeout_ms,
|
||||||
|
unsubscribe_timeout_ms: std::option::Option::Some(endpoint.unsubscribe_timeout_ms),
|
||||||
|
auto_reconnect: std::option::Option::Some(endpoint.auto_reconnect),
|
||||||
|
role_count: bounded_len(endpoint.roles.len()),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return DemoConfigDiagnosticPayload {
|
||||||
|
sources: std::vec![
|
||||||
|
source_diagnostic("composition", state.config_path()),
|
||||||
|
source_diagnostic("logging", state.logging_config_path()),
|
||||||
|
source_diagnostic("transport", state.transport_config_path()),
|
||||||
|
source_diagnostic("listeners", state.listeners_config_path()),
|
||||||
|
source_diagnostic("store", state.store_config_path()),
|
||||||
|
source_diagnostic("wallet", state.wallet_config_path()),
|
||||||
|
source_diagnostic("execution", state.execution_config_path()),
|
||||||
|
],
|
||||||
|
endpoints,
|
||||||
|
store: DemoConfigStoreDiagnosticPayload {
|
||||||
|
enabled: profile.database.enabled,
|
||||||
|
backend: profile.database.backend.clone(),
|
||||||
|
postgres_url_state: configured_state(profile.database.postgres.url.as_str()),
|
||||||
|
postgres_max_connections: profile.database.postgres.max_connections,
|
||||||
|
postgres_connect_timeout_ms: profile.database.postgres.connect_timeout_ms,
|
||||||
|
postgres_auto_initialize_schema: profile.database.postgres.auto_initialize_schema,
|
||||||
|
sqlite_path_state: configured_state(profile.database.sqlite.path.as_str()),
|
||||||
|
sqlite_max_connections: profile.database.sqlite.max_connections,
|
||||||
|
sqlite_auto_initialize_schema: profile.database.sqlite.auto_initialize_schema,
|
||||||
|
},
|
||||||
|
wallet: DemoConfigWalletDiagnosticPayload {
|
||||||
|
wallet_directory_state: configured_state(profile.wallet.wallet_dir.as_str()),
|
||||||
|
cluster: profile.wallet.cluster.clone(),
|
||||||
|
temporary_wallet_enabled: profile.wallet.temporary_wallet_enabled,
|
||||||
|
temporary_wallet_alias: profile.wallet.temporary_wallet_alias.clone(),
|
||||||
|
temporary_wallet_persist: profile.wallet.temporary_wallet_persist,
|
||||||
|
},
|
||||||
|
execution: execution_diagnostic(&profile.execution),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn source_diagnostic(category: &str, path: &str) -> DemoConfigSourceDiagnosticPayload {
|
||||||
|
return DemoConfigSourceDiagnosticPayload {
|
||||||
|
category: category.to_string(),
|
||||||
|
path: path.to_string(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn configured_state(value: &str) -> std::string::String {
|
||||||
|
if value.trim().is_empty() {
|
||||||
|
return "missing".to_string();
|
||||||
|
}
|
||||||
|
return "configured".to_string();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bounded_len(value: usize) -> u32 {
|
||||||
|
return match u32::try_from(value) {
|
||||||
|
std::result::Result::Ok(count) => count,
|
||||||
|
std::result::Result::Err(_) => u32::MAX,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn execution_diagnostic(
|
||||||
|
execution: &ks_config::ExecutionConfig,
|
||||||
|
) -> DemoConfigExecutionDiagnosticPayload {
|
||||||
|
return DemoConfigExecutionDiagnosticPayload {
|
||||||
|
localnet_send_enabled: execution.localnet_send_enabled,
|
||||||
|
devnet_send_enabled: execution.devnet_send_enabled,
|
||||||
|
testnet_send_enabled: execution.testnet_send_enabled,
|
||||||
|
mainnet_send_enabled: execution.mainnet_send_enabled,
|
||||||
|
dry_run_default: execution.dry_run_default,
|
||||||
|
require_simulation: execution.require_simulation,
|
||||||
|
require_operator_confirmation: execution.require_operator_confirmation,
|
||||||
|
localnet_max_spend_lamports: execution.localnet_max_spend_lamports,
|
||||||
|
devnet_max_spend_lamports: execution.devnet_max_spend_lamports,
|
||||||
|
testnet_max_spend_lamports: execution.testnet_max_spend_lamports,
|
||||||
|
mainnet_max_spend_lamports: execution.mainnet_max_spend_lamports,
|
||||||
|
max_fee_lamports: execution.max_fee_lamports,
|
||||||
|
max_compute_unit_price_micro_lamports: execution.max_compute_unit_price_micro_lamports,
|
||||||
|
recent_blockhash_max_age_slots: execution.recent_blockhash_max_age_slots,
|
||||||
|
send_max_retries: execution.send_max_retries,
|
||||||
|
confirmation_poll_interval_ms: execution.confirmation_poll_interval_ms,
|
||||||
|
confirmation_max_attempts: execution.confirmation_max_attempts,
|
||||||
|
devnet_airdrop_max_lamports: execution.devnet_airdrop_max_lamports,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,10 +445,126 @@ pub(crate) fn demo_config_payload(state: &crate::AppState) -> crate::DemoConfigP
|
|||||||
mod tests {
|
mod tests {
|
||||||
use ts_rs::TS; // rust-rules: trait-import
|
use ts_rs::TS; // rust-rules: trait-import
|
||||||
|
|
||||||
|
fn active_fixture_profile() -> ks_config::ProfileConfig {
|
||||||
|
let parsed = ks_config::parse_config_json(include_str!(
|
||||||
|
"../../test-fixtures/config/resolved.app.config.json"
|
||||||
|
));
|
||||||
|
let config = match parsed {
|
||||||
|
std::result::Result::Ok(value) => value,
|
||||||
|
std::result::Result::Err(error) => panic!("resolved fixture must parse: {error}"),
|
||||||
|
};
|
||||||
|
return match ks_config::active_profile(&config) {
|
||||||
|
std::result::Result::Ok(value) => value.clone(),
|
||||||
|
std::result::Result::Err(error) => {
|
||||||
|
panic!("resolved fixture active profile must exist: {error}")
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn desktop_fixture() -> crate::DesktopApplicationConfig {
|
||||||
|
return crate::DesktopApplicationConfig {
|
||||||
|
name: "kb-app-demo-desktop".to_string(),
|
||||||
|
environment: "test".to_string(),
|
||||||
|
demo: crate::DesktopDemoConfig {
|
||||||
|
live_demo_enabled: true,
|
||||||
|
trading_demo_enabled: false,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn payload_binding_uses_desktop_path() {
|
fn payload_binding_uses_desktop_path() {
|
||||||
let config = ts_rs::Config::default();
|
let config = ts_rs::Config::default();
|
||||||
let declaration = <crate::DemoConfigPayload as TS>::decl(&config);
|
let declaration = <crate::DemoConfigPayload as TS>::decl(&config);
|
||||||
assert!(declaration.contains("DemoConfigPayload"));
|
assert!(declaration.contains("DemoConfigPayload"));
|
||||||
|
assert!(declaration.contains("DemoConfigPublicPayload"));
|
||||||
|
assert!(declaration.contains("DemoConfigDiagnosticPayload"));
|
||||||
|
assert!(!declaration.contains("AppConfig"));
|
||||||
|
assert!(!declaration.contains("ProfileConfig"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn public_projection_excludes_internal_execution_and_storage_fields() {
|
||||||
|
let profile = active_fixture_profile();
|
||||||
|
let payload = super::public_config_payload(&profile, &desktop_fixture());
|
||||||
|
let serialized = match serde_json::to_string(&payload) {
|
||||||
|
std::result::Result::Ok(value) => value,
|
||||||
|
std::result::Result::Err(error) => panic!("public payload must serialize: {error}"),
|
||||||
|
};
|
||||||
|
assert!(!serialized.contains("mainnet_send_enabled"));
|
||||||
|
assert!(!serialized.contains("postgres"));
|
||||||
|
assert!(!serialized.contains("wallet_dir"));
|
||||||
|
assert!(!serialized.contains("url"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn public_and_diagnostic_projections_never_serialize_secret_canaries() {
|
||||||
|
let mut profile = active_fixture_profile();
|
||||||
|
profile.database.postgres.url =
|
||||||
|
"postgres://operator:POSTGRES-SECRET-CANARY@localhost/solana".to_string();
|
||||||
|
profile.database.sqlite.path = "/private/SQLITE-PATH-CANARY.sqlite".to_string();
|
||||||
|
profile.wallet.wallet_dir = "/private/WALLET-PATH-CANARY".to_string();
|
||||||
|
if let std::option::Option::Some(endpoint) = profile.solana.http_endpoints.first_mut() {
|
||||||
|
endpoint.url = "https://provider.invalid/?api-key=HELIUS-SECRET-CANARY".to_string();
|
||||||
|
}
|
||||||
|
if let std::option::Option::Some(endpoint) = profile.solana.ws_endpoints.first_mut() {
|
||||||
|
endpoint.url = "wss://provider.invalid/WS-SECRET-CANARY".to_string();
|
||||||
|
}
|
||||||
|
let public = super::public_config_payload(&profile, &desktop_fixture());
|
||||||
|
let diagnostics = super::DemoConfigDiagnosticPayload {
|
||||||
|
sources: std::vec![],
|
||||||
|
endpoints: profile
|
||||||
|
.solana
|
||||||
|
.http_endpoints
|
||||||
|
.iter()
|
||||||
|
.map(|endpoint| {
|
||||||
|
return super::DemoConfigEndpointDiagnosticPayload {
|
||||||
|
kind: "http".to_string(),
|
||||||
|
name: endpoint.name.clone(),
|
||||||
|
enabled: endpoint.enabled,
|
||||||
|
provider: endpoint.provider.clone(),
|
||||||
|
cluster: endpoint.cluster.clone(),
|
||||||
|
url_state: super::configured_state(endpoint.url.as_str()),
|
||||||
|
connect_timeout_ms: endpoint.connect_timeout_ms,
|
||||||
|
request_timeout_ms: endpoint.request_timeout_ms,
|
||||||
|
unsubscribe_timeout_ms: std::option::Option::None,
|
||||||
|
auto_reconnect: std::option::Option::None,
|
||||||
|
role_count: super::bounded_len(endpoint.roles.len()),
|
||||||
|
};
|
||||||
|
})
|
||||||
|
.collect::<std::vec::Vec<super::DemoConfigEndpointDiagnosticPayload>>(),
|
||||||
|
store: super::DemoConfigStoreDiagnosticPayload {
|
||||||
|
enabled: profile.database.enabled,
|
||||||
|
backend: profile.database.backend.clone(),
|
||||||
|
postgres_url_state: super::configured_state(profile.database.postgres.url.as_str()),
|
||||||
|
postgres_max_connections: profile.database.postgres.max_connections,
|
||||||
|
postgres_connect_timeout_ms: profile.database.postgres.connect_timeout_ms,
|
||||||
|
postgres_auto_initialize_schema: profile.database.postgres.auto_initialize_schema,
|
||||||
|
sqlite_path_state: super::configured_state(profile.database.sqlite.path.as_str()),
|
||||||
|
sqlite_max_connections: profile.database.sqlite.max_connections,
|
||||||
|
sqlite_auto_initialize_schema: profile.database.sqlite.auto_initialize_schema,
|
||||||
|
},
|
||||||
|
wallet: super::DemoConfigWalletDiagnosticPayload {
|
||||||
|
wallet_directory_state: super::configured_state(profile.wallet.wallet_dir.as_str()),
|
||||||
|
cluster: profile.wallet.cluster.clone(),
|
||||||
|
temporary_wallet_enabled: profile.wallet.temporary_wallet_enabled,
|
||||||
|
temporary_wallet_alias: profile.wallet.temporary_wallet_alias.clone(),
|
||||||
|
temporary_wallet_persist: profile.wallet.temporary_wallet_persist,
|
||||||
|
},
|
||||||
|
execution: super::execution_diagnostic(&profile.execution),
|
||||||
|
};
|
||||||
|
let serialized = match serde_json::to_string(&(public, diagnostics)) {
|
||||||
|
std::result::Result::Ok(value) => value,
|
||||||
|
std::result::Result::Err(error) => panic!("safe projections must serialize: {error}"),
|
||||||
|
};
|
||||||
|
for secret in [
|
||||||
|
"POSTGRES-SECRET-CANARY",
|
||||||
|
"SQLITE-PATH-CANARY",
|
||||||
|
"WALLET-PATH-CANARY",
|
||||||
|
"HELIUS-SECRET-CANARY",
|
||||||
|
"WS-SECRET-CANARY",
|
||||||
|
] {
|
||||||
|
assert!(!serialized.contains(secret));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// file: kb-app-demo-desktop/src/demo_http.rs
|
// file: kb-app-demo-desktop/src/demo_http.rs
|
||||||
// version: 14
|
// version: 16
|
||||||
|
|
||||||
//! HTTP JSON-RPC demo commands.
|
//! HTTP JSON-RPC demo commands.
|
||||||
|
|
||||||
@@ -53,6 +53,24 @@ pub(crate) struct DemoHttpOptionsPayload {
|
|||||||
pub(crate) methods: std::vec::Vec<crate::DemoHttpMethodOption>,
|
pub(crate) methods: std::vec::Vec<crate::DemoHttpMethodOption>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// UI-safe snapshot of one configured HTTP endpoint.
|
||||||
|
#[derive(Clone, Debug, serde::Serialize, TS)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
#[ts(
|
||||||
|
export,
|
||||||
|
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_http/DemoHttpEndpointPayload.ts"
|
||||||
|
)]
|
||||||
|
pub(crate) struct DemoHttpEndpointPayload {
|
||||||
|
/// Logical endpoint name.
|
||||||
|
pub(crate) endpoint_name: std::string::String,
|
||||||
|
/// Provider name.
|
||||||
|
pub(crate) provider: std::string::String,
|
||||||
|
/// UI-safe role and local-limit snapshots.
|
||||||
|
pub(crate) roles: std::vec::Vec<crate::DemoEndpointRolePayload>,
|
||||||
|
/// Local endpoint status.
|
||||||
|
pub(crate) status: std::string::String,
|
||||||
|
}
|
||||||
|
|
||||||
/// Request payload for one HTTP JSON-RPC demo execution.
|
/// Request payload for one HTTP JSON-RPC demo execution.
|
||||||
#[derive(Clone, Debug, serde::Deserialize, TS)]
|
#[derive(Clone, Debug, serde::Deserialize, TS)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
@@ -85,8 +103,6 @@ pub(crate) struct DemoHttpExecutionPayload {
|
|||||||
pub(crate) endpoint_name: std::string::String,
|
pub(crate) endpoint_name: std::string::String,
|
||||||
/// Selected provider name.
|
/// Selected provider name.
|
||||||
pub(crate) provider: std::string::String,
|
pub(crate) provider: std::string::String,
|
||||||
/// Selected endpoint URL.
|
|
||||||
pub(crate) endpoint_url: std::string::String,
|
|
||||||
/// Required role used by the selection.
|
/// Required role used by the selection.
|
||||||
pub(crate) role: std::string::String,
|
pub(crate) role: std::string::String,
|
||||||
/// JSON-RPC method name.
|
/// JSON-RPC method name.
|
||||||
@@ -146,7 +162,6 @@ pub(crate) async fn demo_http_execute_request(
|
|||||||
return std::result::Result::Ok(crate::DemoHttpExecutionPayload {
|
return std::result::Result::Ok(crate::DemoHttpExecutionPayload {
|
||||||
endpoint_name: selected_client.endpoint_name().to_string(),
|
endpoint_name: selected_client.endpoint_name().to_string(),
|
||||||
provider: selected_client.provider().to_string(),
|
provider: selected_client.provider().to_string(),
|
||||||
endpoint_url: selected_client.endpoint_url().to_string(),
|
|
||||||
role,
|
role,
|
||||||
request_kind: ks_onchain_transport::request_kind_from_method(&method),
|
request_kind: ks_onchain_transport::request_kind_from_method(&method),
|
||||||
method,
|
method,
|
||||||
@@ -157,8 +172,13 @@ pub(crate) async fn demo_http_execute_request(
|
|||||||
|
|
||||||
pub(crate) fn demo_http_list_pool_clients(
|
pub(crate) fn demo_http_list_pool_clients(
|
||||||
state: tauri::State<'_, crate::AppState>,
|
state: tauri::State<'_, crate::AppState>,
|
||||||
) -> std::vec::Vec<ks_onchain_transport::HttpPoolClientSnapshot> {
|
) -> std::vec::Vec<crate::DemoHttpEndpointPayload> {
|
||||||
return state.http_pool().snapshot();
|
let snapshots = state.http_pool().snapshot();
|
||||||
|
let mut endpoints = std::vec::Vec::new();
|
||||||
|
for snapshot in snapshots {
|
||||||
|
endpoints.push(http_endpoint_payload(snapshot));
|
||||||
|
}
|
||||||
|
return endpoints;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn demo_http_options(
|
pub(crate) fn demo_http_options(
|
||||||
@@ -170,6 +190,21 @@ pub(crate) fn demo_http_options(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn http_endpoint_payload(
|
||||||
|
snapshot: ks_onchain_transport::HttpPoolClientSnapshot,
|
||||||
|
) -> crate::DemoHttpEndpointPayload {
|
||||||
|
let mut roles = std::vec::Vec::new();
|
||||||
|
for role in snapshot.roles {
|
||||||
|
roles.push(crate::DemoEndpointRolePayload::from_snapshot(role));
|
||||||
|
}
|
||||||
|
return crate::DemoHttpEndpointPayload {
|
||||||
|
endpoint_name: snapshot.endpoint_name,
|
||||||
|
provider: snapshot.provider,
|
||||||
|
roles,
|
||||||
|
status: snapshot.status,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
fn build_http_role_options(
|
fn build_http_role_options(
|
||||||
snapshots: std::vec::Vec<ks_onchain_transport::HttpPoolClientSnapshot>,
|
snapshots: std::vec::Vec<ks_onchain_transport::HttpPoolClientSnapshot>,
|
||||||
) -> std::vec::Vec<crate::DemoHttpRoleOption> {
|
) -> std::vec::Vec<crate::DemoHttpRoleOption> {
|
||||||
@@ -412,4 +447,23 @@ mod tests {
|
|||||||
}
|
}
|
||||||
assert!(!options.is_empty());
|
assert!(!options.is_empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn endpoint_payload_never_serializes_resolved_url() {
|
||||||
|
let snapshot = ks_onchain_transport::HttpPoolClientSnapshot {
|
||||||
|
endpoint_name: "helius".to_string(),
|
||||||
|
provider: "helius".to_string(),
|
||||||
|
roles: std::vec::Vec::new(),
|
||||||
|
status: "idle".to_string(),
|
||||||
|
};
|
||||||
|
let payload = super::http_endpoint_payload(snapshot);
|
||||||
|
let serialized = match serde_json::to_string(&payload) {
|
||||||
|
std::result::Result::Ok(value) => value,
|
||||||
|
std::result::Result::Err(error) => {
|
||||||
|
panic!("cannot serialize HTTP endpoint payload: {error}")
|
||||||
|
},
|
||||||
|
};
|
||||||
|
assert!(!serialized.contains("HTTP-SECRET-CANARY"));
|
||||||
|
assert!(!serialized.contains("endpointUrl"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// file: kb-app-demo-desktop/src/demo_spl_token_2022.rs
|
// file: kb-app-demo-desktop/src/demo_spl_token_2022.rs
|
||||||
// version: 14
|
// version: 15
|
||||||
|
|
||||||
//! Thin Tauri adapter for independent public Token-2022 Devnet validation scenarios.
|
//! Thin Tauri adapter for independent public Token-2022 Devnet validation scenarios.
|
||||||
|
|
||||||
@@ -13,8 +13,6 @@ use ts_rs::TS; // rust-rules: derive-import
|
|||||||
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_spl_token_2022/DemoSplToken2022FixturePayload.ts"
|
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_spl_token_2022/DemoSplToken2022FixturePayload.ts"
|
||||||
)]
|
)]
|
||||||
pub(crate) struct DemoSplToken2022FixturePayload {
|
pub(crate) struct DemoSplToken2022FixturePayload {
|
||||||
/// Fixture file used by the application.
|
|
||||||
pub(crate) fixture_path: std::string::String,
|
|
||||||
/// Token-2022 program ID.
|
/// Token-2022 program ID.
|
||||||
pub(crate) program_id: std::string::String,
|
pub(crate) program_id: std::string::String,
|
||||||
/// Mint account.
|
/// Mint account.
|
||||||
@@ -231,11 +229,10 @@ pub(crate) fn demo_spl_token_2022_fixture(
|
|||||||
let fixture_path = wallet_dir.join("spl_token_2022_validation").join("fixture.env");
|
let fixture_path = wallet_dir.join("spl_token_2022_validation").join("fixture.env");
|
||||||
let contents = match std::fs::read_to_string(&fixture_path) {
|
let contents = match std::fs::read_to_string(&fixture_path) {
|
||||||
std::result::Result::Ok(value) => value,
|
std::result::Result::Ok(value) => value,
|
||||||
std::result::Result::Err(error) => {
|
std::result::Result::Err(_) => {
|
||||||
return std::result::Result::Err(format!(
|
return std::result::Result::Err(
|
||||||
"unable to read Token-2022 fixture {}: {error}",
|
"unable to read configured Token-2022 fixture".to_string(),
|
||||||
fixture_path.display()
|
);
|
||||||
));
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
let values = parse_fixture(contents.as_str());
|
let values = parse_fixture(contents.as_str());
|
||||||
@@ -292,7 +289,6 @@ pub(crate) fn demo_spl_token_2022_fixture(
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
return std::result::Result::Ok(crate::DemoSplToken2022FixturePayload {
|
return std::result::Result::Ok(crate::DemoSplToken2022FixturePayload {
|
||||||
fixture_path: fixture_path.display().to_string(),
|
|
||||||
program_id,
|
program_id,
|
||||||
mint,
|
mint,
|
||||||
source,
|
source,
|
||||||
@@ -581,6 +577,31 @@ mod tests {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn fixture_payload_never_serializes_wallet_path() {
|
||||||
|
let payload = crate::DemoSplToken2022FixturePayload {
|
||||||
|
program_id: "program".to_string(),
|
||||||
|
mint: "mint".to_string(),
|
||||||
|
source: "source".to_string(),
|
||||||
|
destination: "destination".to_string(),
|
||||||
|
close_account: "close".to_string(),
|
||||||
|
delegate: "delegate".to_string(),
|
||||||
|
authority: "authority".to_string(),
|
||||||
|
freeze_authority: "freeze".to_string(),
|
||||||
|
decimals: 9,
|
||||||
|
mint_amount_raw: "1".to_string(),
|
||||||
|
transfer_amount_raw: "1".to_string(),
|
||||||
|
approve_amount_raw: "1".to_string(),
|
||||||
|
burn_amount_raw: "1".to_string(),
|
||||||
|
};
|
||||||
|
let serialized = serde_json::to_string(&payload);
|
||||||
|
assert!(serialized.is_ok());
|
||||||
|
if let std::result::Result::Ok(json) = serialized {
|
||||||
|
assert!(!json.contains("fixturePath"));
|
||||||
|
assert!(!json.contains("WALLET-PATH-CANARY"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn every_public_scenario_builds_one_typed_operation() {
|
fn every_public_scenario_builds_one_typed_operation() {
|
||||||
for scenario in [
|
for scenario in [
|
||||||
|
|||||||
52
kb-app-demo-desktop/src/demo_transport.rs
Normal file
52
kb-app-demo-desktop/src/demo_transport.rs
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
// file: kb-app-demo-desktop/src/demo_transport.rs
|
||||||
|
// version: 1
|
||||||
|
|
||||||
|
//! UI-safe transport DTOs shared by HTTP and WebSocket demo surfaces.
|
||||||
|
|
||||||
|
use ts_rs::TS; // rust-rules: derive-import
|
||||||
|
|
||||||
|
/// UI-safe endpoint role and local routing limits.
|
||||||
|
#[derive(Clone, Debug, serde::Serialize, TS)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
#[ts(
|
||||||
|
export,
|
||||||
|
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_transport/DemoEndpointRolePayload.ts"
|
||||||
|
)]
|
||||||
|
pub(crate) struct DemoEndpointRolePayload {
|
||||||
|
/// Role code used by endpoint pools.
|
||||||
|
pub(crate) role: std::string::String,
|
||||||
|
/// Whether the role is enabled.
|
||||||
|
pub(crate) enabled: bool,
|
||||||
|
/// Request or subscription kinds handled by this role.
|
||||||
|
pub(crate) request_kinds: std::vec::Vec<std::string::String>,
|
||||||
|
/// Role priority where lower values are preferred.
|
||||||
|
pub(crate) priority: u32,
|
||||||
|
/// Requests per second allowed for this role.
|
||||||
|
pub(crate) requests_per_second: u32,
|
||||||
|
/// Burst capacity allowed for this role.
|
||||||
|
pub(crate) burst_capacity: u32,
|
||||||
|
/// Maximum concurrent requests allowed for this role.
|
||||||
|
pub(crate) max_concurrent_requests: u32,
|
||||||
|
/// Maximum subscriptions allowed for this role.
|
||||||
|
pub(crate) max_subscriptions: u32,
|
||||||
|
/// Pause after a rate limit response in milliseconds.
|
||||||
|
#[ts(type = "number")]
|
||||||
|
pub(crate) pause_after_rate_limit_ms: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl crate::DemoEndpointRolePayload {
|
||||||
|
/// Converts one backend transport role snapshot into the UI-safe application contract.
|
||||||
|
pub(crate) fn from_snapshot(snapshot: ks_onchain_transport::EndpointRoleSnapshot) -> Self {
|
||||||
|
return Self {
|
||||||
|
role: snapshot.role,
|
||||||
|
enabled: snapshot.enabled,
|
||||||
|
request_kinds: snapshot.request_kinds,
|
||||||
|
priority: snapshot.priority,
|
||||||
|
requests_per_second: snapshot.requests_per_second,
|
||||||
|
burst_capacity: snapshot.burst_capacity,
|
||||||
|
max_concurrent_requests: snapshot.max_concurrent_requests,
|
||||||
|
max_subscriptions: snapshot.max_subscriptions,
|
||||||
|
pause_after_rate_limit_ms: snapshot.pause_after_rate_limit_ms,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
// file: kb-app-demo-desktop/src/demo_ws.rs
|
// file: kb-app-demo-desktop/src/demo_ws.rs
|
||||||
// version: 20
|
// version: 23
|
||||||
|
|
||||||
//! Standard Solana WebSocket demo commands backed by `ks_onchain_transport::WsSession`.
|
//! Standard Solana WebSocket demo commands backed by `ks_onchain_transport::WsSession`.
|
||||||
|
|
||||||
@@ -59,6 +59,24 @@ pub(crate) struct DemoWsOptionsPayload {
|
|||||||
pub(crate) methods: std::vec::Vec<crate::DemoWsMethodOption>,
|
pub(crate) methods: std::vec::Vec<crate::DemoWsMethodOption>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// UI-safe snapshot of one configured WebSocket endpoint.
|
||||||
|
#[derive(Clone, Debug, serde::Serialize, TS)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
#[ts(
|
||||||
|
export,
|
||||||
|
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_ws/DemoWsEndpointPayload.ts"
|
||||||
|
)]
|
||||||
|
pub(crate) struct DemoWsEndpointPayload {
|
||||||
|
/// Logical endpoint name.
|
||||||
|
pub(crate) endpoint_name: std::string::String,
|
||||||
|
/// Provider name.
|
||||||
|
pub(crate) provider: std::string::String,
|
||||||
|
/// UI-safe role and local-limit snapshots.
|
||||||
|
pub(crate) roles: std::vec::Vec<crate::DemoEndpointRolePayload>,
|
||||||
|
/// Local endpoint status.
|
||||||
|
pub(crate) status: std::string::String,
|
||||||
|
}
|
||||||
|
|
||||||
/// Request payload for one WebSocket subscription demo command.
|
/// Request payload for one WebSocket subscription demo command.
|
||||||
#[derive(Clone, Debug, serde::Deserialize, TS)]
|
#[derive(Clone, Debug, serde::Deserialize, TS)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
@@ -91,8 +109,6 @@ pub(crate) struct DemoWsExecutionPayload {
|
|||||||
pub(crate) endpoint_name: std::string::String,
|
pub(crate) endpoint_name: std::string::String,
|
||||||
/// Selected provider name.
|
/// Selected provider name.
|
||||||
pub(crate) provider: std::string::String,
|
pub(crate) provider: std::string::String,
|
||||||
/// Selected endpoint URL.
|
|
||||||
pub(crate) endpoint_url: std::string::String,
|
|
||||||
/// Required role used by the selection.
|
/// Required role used by the selection.
|
||||||
pub(crate) role: std::string::String,
|
pub(crate) role: std::string::String,
|
||||||
/// JSON-RPC method name.
|
/// JSON-RPC method name.
|
||||||
@@ -120,8 +136,6 @@ pub(crate) struct DemoWsStatusPayload {
|
|||||||
pub(crate) connected: bool,
|
pub(crate) connected: bool,
|
||||||
/// Selected endpoint name.
|
/// Selected endpoint name.
|
||||||
pub(crate) endpoint_name: std::option::Option<std::string::String>,
|
pub(crate) endpoint_name: std::option::Option<std::string::String>,
|
||||||
/// Selected endpoint URL.
|
|
||||||
pub(crate) endpoint_url: std::option::Option<std::string::String>,
|
|
||||||
/// Last subscription method.
|
/// Last subscription method.
|
||||||
pub(crate) method: std::option::Option<std::string::String>,
|
pub(crate) method: std::option::Option<std::string::String>,
|
||||||
/// Last unsubscribe method.
|
/// Last unsubscribe method.
|
||||||
@@ -230,7 +244,6 @@ pub(crate) async fn demo_ws_connect(
|
|||||||
return std::result::Result::Ok(crate::DemoWsExecutionPayload {
|
return std::result::Result::Ok(crate::DemoWsExecutionPayload {
|
||||||
endpoint_name: selected_client.endpoint_name().to_string(),
|
endpoint_name: selected_client.endpoint_name().to_string(),
|
||||||
provider: selected_client.provider().to_string(),
|
provider: selected_client.provider().to_string(),
|
||||||
endpoint_url: selected_client.endpoint_url().to_string(),
|
|
||||||
role,
|
role,
|
||||||
method: method.clone(),
|
method: method.clone(),
|
||||||
request_kind: ks_onchain_transport::request_kind_from_method(&method),
|
request_kind: ks_onchain_transport::request_kind_from_method(&method),
|
||||||
@@ -259,15 +272,17 @@ pub(crate) async fn demo_ws_status(
|
|||||||
/// Lists WebSocket endpoints available through the configured pool.
|
/// Lists WebSocket endpoints available through the configured pool.
|
||||||
pub(crate) fn demo_ws_list_pool_clients(
|
pub(crate) fn demo_ws_list_pool_clients(
|
||||||
state: tauri::State<'_, crate::AppState>,
|
state: tauri::State<'_, crate::AppState>,
|
||||||
) -> std::result::Result<
|
) -> std::result::Result<std::vec::Vec<crate::DemoWsEndpointPayload>, std::string::String> {
|
||||||
std::vec::Vec<ks_onchain_transport::WsPoolClientSnapshot>,
|
|
||||||
std::string::String,
|
|
||||||
> {
|
|
||||||
let pool = match state.demo_ws_pool() {
|
let pool = match state.demo_ws_pool() {
|
||||||
std::result::Result::Ok(value) => value,
|
std::result::Result::Ok(value) => value,
|
||||||
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
|
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
|
||||||
};
|
};
|
||||||
return std::result::Result::Ok(pool.snapshot());
|
let snapshots = pool.snapshot();
|
||||||
|
let mut endpoints = std::vec::Vec::new();
|
||||||
|
for snapshot in snapshots {
|
||||||
|
endpoints.push(ws_endpoint_payload(snapshot));
|
||||||
|
}
|
||||||
|
return std::result::Result::Ok(endpoints);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Lists selectable WebSocket roles and methods for the demo UI.
|
/// Lists selectable WebSocket roles and methods for the demo UI.
|
||||||
@@ -393,7 +408,7 @@ async fn ensure_session(
|
|||||||
if let std::option::Option::Some(session) = existing {
|
if let std::option::Option::Some(session) = existing {
|
||||||
let snapshot = session.snapshot().await;
|
let snapshot = session.snapshot().await;
|
||||||
if snapshot.state != ks_onchain_transport::WsSessionState::Disconnected {
|
if snapshot.state != ks_onchain_transport::WsSessionState::Disconnected {
|
||||||
if snapshot.endpoint_url != selected_client.endpoint_url() {
|
if snapshot.endpoint_name.as_str() != selected_client.endpoint_name() {
|
||||||
return std::result::Result::Err(format!(
|
return std::result::Result::Err(format!(
|
||||||
"demo WebSocket session already uses endpoint '{}'; disconnect before selecting '{}'",
|
"demo WebSocket session already uses endpoint '{}'; disconnect before selecting '{}'",
|
||||||
snapshot.endpoint_name,
|
snapshot.endpoint_name,
|
||||||
@@ -569,7 +584,6 @@ fn status_from_snapshot(
|
|||||||
return crate::DemoWsStatusPayload {
|
return crate::DemoWsStatusPayload {
|
||||||
connected: snapshot.state != ks_onchain_transport::WsSessionState::Disconnected,
|
connected: snapshot.state != ks_onchain_transport::WsSessionState::Disconnected,
|
||||||
endpoint_name: std::option::Option::Some(snapshot.endpoint_name),
|
endpoint_name: std::option::Option::Some(snapshot.endpoint_name),
|
||||||
endpoint_url: std::option::Option::Some(snapshot.endpoint_url),
|
|
||||||
method,
|
method,
|
||||||
unsubscribe_method,
|
unsubscribe_method,
|
||||||
subscription_id,
|
subscription_id,
|
||||||
@@ -585,7 +599,6 @@ fn disconnected_status() -> crate::DemoWsStatusPayload {
|
|||||||
return crate::DemoWsStatusPayload {
|
return crate::DemoWsStatusPayload {
|
||||||
connected: false,
|
connected: false,
|
||||||
endpoint_name: std::option::Option::None,
|
endpoint_name: std::option::Option::None,
|
||||||
endpoint_url: std::option::Option::None,
|
|
||||||
method: std::option::Option::None,
|
method: std::option::Option::None,
|
||||||
unsubscribe_method: std::option::Option::None,
|
unsubscribe_method: std::option::Option::None,
|
||||||
subscription_id: std::option::Option::None,
|
subscription_id: std::option::Option::None,
|
||||||
@@ -594,6 +607,21 @@ fn disconnected_status() -> crate::DemoWsStatusPayload {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn ws_endpoint_payload(
|
||||||
|
snapshot: ks_onchain_transport::WsPoolClientSnapshot,
|
||||||
|
) -> crate::DemoWsEndpointPayload {
|
||||||
|
let mut roles = std::vec::Vec::new();
|
||||||
|
for role in snapshot.roles {
|
||||||
|
roles.push(crate::DemoEndpointRolePayload::from_snapshot(role));
|
||||||
|
}
|
||||||
|
return crate::DemoWsEndpointPayload {
|
||||||
|
endpoint_name: snapshot.endpoint_name,
|
||||||
|
provider: snapshot.provider,
|
||||||
|
roles,
|
||||||
|
status: snapshot.status,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
fn build_ws_role_options(
|
fn build_ws_role_options(
|
||||||
snapshots: std::vec::Vec<ks_onchain_transport::WsPoolClientSnapshot>,
|
snapshots: std::vec::Vec<ks_onchain_transport::WsPoolClientSnapshot>,
|
||||||
) -> std::vec::Vec<crate::DemoWsRoleOption> {
|
) -> std::vec::Vec<crate::DemoWsRoleOption> {
|
||||||
@@ -957,10 +985,46 @@ mod tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn endpoint_and_status_payloads_never_serialize_resolved_url() {
|
||||||
|
let endpoint_snapshot = ks_onchain_transport::WsPoolClientSnapshot {
|
||||||
|
endpoint_name: "helius".to_string(),
|
||||||
|
provider: "helius".to_string(),
|
||||||
|
roles: std::vec::Vec::new(),
|
||||||
|
status: "idle".to_string(),
|
||||||
|
};
|
||||||
|
let endpoint_payload = super::ws_endpoint_payload(endpoint_snapshot);
|
||||||
|
let endpoint_json = match serde_json::to_string(&endpoint_payload) {
|
||||||
|
std::result::Result::Ok(value) => value,
|
||||||
|
std::result::Result::Err(error) => {
|
||||||
|
panic!("cannot serialize WebSocket endpoint payload: {error}")
|
||||||
|
},
|
||||||
|
};
|
||||||
|
assert!(!endpoint_json.contains("WS-SECRET-CANARY"));
|
||||||
|
assert!(!endpoint_json.contains("endpointUrl"));
|
||||||
|
let status = super::status_from_snapshot(ks_onchain_transport::WsSessionSnapshot {
|
||||||
|
endpoint_name: "helius".to_string(),
|
||||||
|
provider: "helius".to_string(),
|
||||||
|
state: ks_onchain_transport::WsSessionState::Connected,
|
||||||
|
reconnect_count: 0,
|
||||||
|
capabilities: ks_onchain_transport::StandardWsCapabilities::default(),
|
||||||
|
subscriptions: std::vec::Vec::new(),
|
||||||
|
});
|
||||||
|
let status_json = match serde_json::to_string(&status) {
|
||||||
|
std::result::Result::Ok(value) => value,
|
||||||
|
std::result::Result::Err(error) => {
|
||||||
|
panic!("cannot serialize WebSocket status payload: {error}")
|
||||||
|
},
|
||||||
|
};
|
||||||
|
assert!(!status_json.contains("WS-SECRET-CANARY"));
|
||||||
|
assert!(!status_json.contains("endpointUrl"));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn tauri_numeric_bindings_use_json_compatible_numbers() {
|
fn tauri_numeric_bindings_use_json_compatible_numbers() {
|
||||||
let config = ts_rs::Config::default();
|
let config = ts_rs::Config::default();
|
||||||
let declarations = [
|
let declarations = [
|
||||||
|
<crate::DemoEndpointRolePayload as TS>::decl(&config),
|
||||||
<crate::DemoWsExecutionPayload as TS>::decl(&config),
|
<crate::DemoWsExecutionPayload as TS>::decl(&config),
|
||||||
<crate::DemoWsStatusPayload as TS>::decl(&config),
|
<crate::DemoWsStatusPayload as TS>::decl(&config),
|
||||||
<crate::DemoWsSubscriptionStatusPayload as TS>::decl(&config),
|
<crate::DemoWsSubscriptionStatusPayload as TS>::decl(&config),
|
||||||
|
|||||||
96
kb-app-demo-desktop/src/desktop_config.rs
Normal file
96
kb-app-demo-desktop/src/desktop_config.rs
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
// file: kb-app-demo-desktop/src/desktop_config.rs
|
||||||
|
// version: 2
|
||||||
|
|
||||||
|
//! Desktop-owned application settings embedded in one generic binary composition profile.
|
||||||
|
|
||||||
|
const DESKTOP_APPLICATION_SCHEMA: &str =
|
||||||
|
include_str!("../../config/schemas/kb-app-demo-desktop.application.config.schema.json");
|
||||||
|
|
||||||
|
/// Desktop-owned settings for one selected composition profile.
|
||||||
|
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
|
pub(crate) struct DesktopApplicationConfig {
|
||||||
|
/// Application display/name identity.
|
||||||
|
pub(crate) name: std::string::String,
|
||||||
|
/// Human-readable environment classification.
|
||||||
|
pub(crate) environment: std::string::String,
|
||||||
|
/// Desktop demo feature flags.
|
||||||
|
pub(crate) demo: crate::DesktopDemoConfig,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Desktop-owned demo feature flags.
|
||||||
|
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
|
pub(crate) struct DesktopDemoConfig {
|
||||||
|
/// Enables live demo pages.
|
||||||
|
pub(crate) live_demo_enabled: bool,
|
||||||
|
/// Enables trading demo pages.
|
||||||
|
pub(crate) trading_demo_enabled: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parses and validates desktop-owned settings from one generic composition profile.
|
||||||
|
pub(crate) fn desktop_application_config(
|
||||||
|
profile: &ks_config::CompositionProfileConfig,
|
||||||
|
) -> ks_core::Result<DesktopApplicationConfig> {
|
||||||
|
let application = match profile.application.as_ref() {
|
||||||
|
std::option::Option::Some(value) => value,
|
||||||
|
std::option::Option::None => {
|
||||||
|
return std::result::Result::Err(ks_core::Error::new(
|
||||||
|
"desktop_application_config_missing",
|
||||||
|
profile.name.clone(),
|
||||||
|
));
|
||||||
|
},
|
||||||
|
};
|
||||||
|
match ks_config::validate_json_value_against_schema(
|
||||||
|
DESKTOP_APPLICATION_SCHEMA,
|
||||||
|
application,
|
||||||
|
"desktop_application_config_schema_validation_failed",
|
||||||
|
) {
|
||||||
|
std::result::Result::Ok(()) => (),
|
||||||
|
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||||
|
}
|
||||||
|
return match serde_json::from_value::<DesktopApplicationConfig>(application.clone()) {
|
||||||
|
std::result::Result::Ok(value) => std::result::Result::Ok(value),
|
||||||
|
std::result::Result::Err(_) => std::result::Result::Err(ks_core::Error::new(
|
||||||
|
"desktop_application_config_decode_failed",
|
||||||
|
"desktop application configuration could not be decoded",
|
||||||
|
)),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
#[test]
|
||||||
|
fn default_composition_contains_valid_desktop_application_fragments() {
|
||||||
|
let raw = include_str!("../../config/kb-app-demo-desktop.default.config.json");
|
||||||
|
let composition = match ks_config::parse_composition_json(raw) {
|
||||||
|
std::result::Result::Ok(value) => value,
|
||||||
|
std::result::Result::Err(error) => panic!("default composition must parse: {error}"),
|
||||||
|
};
|
||||||
|
for profile in &composition.profiles {
|
||||||
|
let result = super::desktop_application_config(profile);
|
||||||
|
assert!(result.is_ok());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn application_fragment_rejects_unknown_or_missing_fields() {
|
||||||
|
let profile = ks_config::CompositionProfileConfig {
|
||||||
|
name: "test".to_string(),
|
||||||
|
application: std::option::Option::Some(serde_json::json!({
|
||||||
|
"name": "kb-app-demo-desktop",
|
||||||
|
"environment": "test",
|
||||||
|
"demo": {
|
||||||
|
"live_demo_enabled": true,
|
||||||
|
"trading_demo_enabled": false
|
||||||
|
},
|
||||||
|
"secret": "must-not-be-accepted"
|
||||||
|
})),
|
||||||
|
logging_profile: std::option::Option::None,
|
||||||
|
transport_profile: std::option::Option::None,
|
||||||
|
listeners_profile: std::option::Option::None,
|
||||||
|
store_profile: std::option::Option::None,
|
||||||
|
wallet_profile: std::option::Option::None,
|
||||||
|
execution_profile: std::option::Option::None,
|
||||||
|
};
|
||||||
|
assert!(super::desktop_application_config(&profile).is_err());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
// file: kb-app-demo-desktop/src/lib.rs
|
// file: kb-app-demo-desktop/src/lib.rs
|
||||||
// version: 34
|
// version: 37
|
||||||
|
|
||||||
//! Tauri desktop demo application for `khadhroony-bot3`.
|
//! Tauri desktop demo application for `khadhroony-bot3`.
|
||||||
|
|
||||||
@@ -29,7 +29,9 @@ mod demo_sql_diag;
|
|||||||
mod demo_sql_pg_core;
|
mod demo_sql_pg_core;
|
||||||
mod demo_sql_pg_raw;
|
mod demo_sql_pg_raw;
|
||||||
mod demo_sql_replay_candidates;
|
mod demo_sql_replay_candidates;
|
||||||
|
mod demo_transport;
|
||||||
mod demo_ws;
|
mod demo_ws;
|
||||||
|
mod desktop_config;
|
||||||
mod frontend_log;
|
mod frontend_log;
|
||||||
mod main_window;
|
mod main_window;
|
||||||
mod splash;
|
mod splash;
|
||||||
@@ -64,8 +66,28 @@ pub(crate) use self::demo_backfill::demo_backfill_cancel;
|
|||||||
pub(crate) use self::demo_backfill::demo_backfill_execute;
|
pub(crate) use self::demo_backfill::demo_backfill_execute;
|
||||||
/// Returns endpoint roles, known programs and conservative backfill defaults.
|
/// Returns endpoint roles, known programs and conservative backfill defaults.
|
||||||
pub(crate) use self::demo_backfill::demo_backfill_options;
|
pub(crate) use self::demo_backfill::demo_backfill_options;
|
||||||
|
/// Bounded internal configuration diagnostics shown by the configuration window.
|
||||||
|
pub(crate) use self::demo_config::DemoConfigDiagnosticPayload;
|
||||||
|
/// Bounded endpoint diagnostics shown by the configuration window.
|
||||||
|
pub(crate) use self::demo_config::DemoConfigEndpointDiagnosticPayload;
|
||||||
|
/// Bounded execution diagnostics shown by the configuration window.
|
||||||
|
pub(crate) use self::demo_config::DemoConfigExecutionDiagnosticPayload;
|
||||||
/// Configuration payload shown by the configuration window.
|
/// Configuration payload shown by the configuration window.
|
||||||
pub(crate) use self::demo_config::DemoConfigPayload;
|
pub(crate) use self::demo_config::DemoConfigPayload;
|
||||||
|
/// Public desktop demo feature flags.
|
||||||
|
pub(crate) use self::demo_config::DemoConfigPublicDemoPayload;
|
||||||
|
/// Public endpoint identity shown by the configuration window.
|
||||||
|
pub(crate) use self::demo_config::DemoConfigPublicEndpointPayload;
|
||||||
|
/// Public listener summary shown by the configuration window.
|
||||||
|
pub(crate) use self::demo_config::DemoConfigPublicListenersPayload;
|
||||||
|
/// Explicit public configuration projection shown by the configuration window.
|
||||||
|
pub(crate) use self::demo_config::DemoConfigPublicPayload;
|
||||||
|
/// Bounded source-path diagnostics shown by the configuration window.
|
||||||
|
pub(crate) use self::demo_config::DemoConfigSourceDiagnosticPayload;
|
||||||
|
/// Bounded store diagnostics shown by the configuration window.
|
||||||
|
pub(crate) use self::demo_config::DemoConfigStoreDiagnosticPayload;
|
||||||
|
/// Bounded wallet diagnostics shown by the configuration window.
|
||||||
|
pub(crate) use self::demo_config::DemoConfigWalletDiagnosticPayload;
|
||||||
/// Builds the configuration payload from shared application state.
|
/// Builds the configuration payload from shared application state.
|
||||||
pub(crate) use self::demo_config::demo_config_payload;
|
pub(crate) use self::demo_config::demo_config_payload;
|
||||||
/// Internal demo core extraction item.
|
/// Internal demo core extraction item.
|
||||||
@@ -228,6 +250,8 @@ pub(crate) use self::demo_execution_solana_core::select_devnet_profile;
|
|||||||
pub(crate) use self::demo_execution_spl::DevnetSplValidationScenarioPayload;
|
pub(crate) use self::demo_execution_spl::DevnetSplValidationScenarioPayload;
|
||||||
/// Returns the complete ordered Devnet SPL validation inventory for milestone 0.4.6.
|
/// Returns the complete ordered Devnet SPL validation inventory for milestone 0.4.6.
|
||||||
pub(crate) use self::demo_execution_spl::demo_execution_spl_validation_scenarios;
|
pub(crate) use self::demo_execution_spl::demo_execution_spl_validation_scenarios;
|
||||||
|
/// UI-safe HTTP endpoint snapshot.
|
||||||
|
pub(crate) use self::demo_http::DemoHttpEndpointPayload;
|
||||||
/// HTTP demo response payload.
|
/// HTTP demo response payload.
|
||||||
pub(crate) use self::demo_http::DemoHttpExecutionPayload;
|
pub(crate) use self::demo_http::DemoHttpExecutionPayload;
|
||||||
/// One selectable HTTP JSON-RPC method.
|
/// One selectable HTTP JSON-RPC method.
|
||||||
@@ -336,6 +360,10 @@ pub(crate) use self::demo_sql_replay_candidates::load_demo_sql_replay_entities;
|
|||||||
pub(crate) use self::demo_sql_replay_candidates::load_demo_sql_replay_programs;
|
pub(crate) use self::demo_sql_replay_candidates::load_demo_sql_replay_programs;
|
||||||
/// Loads bounded transaction replay candidates from PostgreSQL.
|
/// Loads bounded transaction replay candidates from PostgreSQL.
|
||||||
pub(crate) use self::demo_sql_replay_candidates::load_demo_sql_replay_transactions;
|
pub(crate) use self::demo_sql_replay_candidates::load_demo_sql_replay_transactions;
|
||||||
|
/// UI-safe endpoint role shared by HTTP and WebSocket diagnostics.
|
||||||
|
pub(crate) use self::demo_transport::DemoEndpointRolePayload;
|
||||||
|
/// UI-safe WebSocket endpoint snapshot.
|
||||||
|
pub(crate) use self::demo_ws::DemoWsEndpointPayload;
|
||||||
/// WebSocket execution response payload.
|
/// WebSocket execution response payload.
|
||||||
pub(crate) use self::demo_ws::DemoWsExecutionPayload;
|
pub(crate) use self::demo_ws::DemoWsExecutionPayload;
|
||||||
/// WebSocket message emitted to the frontend.
|
/// WebSocket message emitted to the frontend.
|
||||||
@@ -368,6 +396,12 @@ pub(crate) use self::demo_ws::demo_ws_status;
|
|||||||
pub(crate) use self::demo_ws::demo_ws_unsubscribe;
|
pub(crate) use self::demo_ws::demo_ws_unsubscribe;
|
||||||
/// Disconnects the persistent WebSocket session during application shutdown.
|
/// Disconnects the persistent WebSocket session during application shutdown.
|
||||||
pub(crate) use self::demo_ws::disconnect_demo_ws_app_state;
|
pub(crate) use self::demo_ws::disconnect_demo_ws_app_state;
|
||||||
|
/// Desktop-owned application settings selected from the active composition profile.
|
||||||
|
pub(crate) use self::desktop_config::DesktopApplicationConfig;
|
||||||
|
/// Desktop-owned demo feature flags.
|
||||||
|
pub(crate) use self::desktop_config::DesktopDemoConfig;
|
||||||
|
/// Parses desktop-owned settings from one composition profile.
|
||||||
|
pub(crate) use self::desktop_config::desktop_application_config;
|
||||||
/// Frontend logging payload.
|
/// Frontend logging payload.
|
||||||
pub(crate) use self::frontend_log::FrontendLogPayload;
|
pub(crate) use self::frontend_log::FrontendLogPayload;
|
||||||
/// Emits one normalized frontend log event.
|
/// Emits one normalized frontend log event.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// file: kb-app-demo-desktop/src/tauri.rs
|
// file: kb-app-demo-desktop/src/tauri.rs
|
||||||
// version: 37
|
// version: 38
|
||||||
|
|
||||||
//! Tauri runtime assembly and private command wrappers.
|
//! Tauri runtime assembly and private command wrappers.
|
||||||
|
|
||||||
@@ -257,7 +257,7 @@ fn open_demo_http_window(
|
|||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
fn demo_http_list_pool_clients(
|
fn demo_http_list_pool_clients(
|
||||||
state: tauri::State<'_, crate::AppState>,
|
state: tauri::State<'_, crate::AppState>,
|
||||||
) -> std::vec::Vec<ks_onchain_transport::HttpPoolClientSnapshot> {
|
) -> std::vec::Vec<crate::DemoHttpEndpointPayload> {
|
||||||
return crate::demo_http_list_pool_clients(state);
|
return crate::demo_http_list_pool_clients(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -284,10 +284,7 @@ fn open_demo_ws_window(
|
|||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
fn demo_ws_list_pool_clients(
|
fn demo_ws_list_pool_clients(
|
||||||
state: tauri::State<'_, crate::AppState>,
|
state: tauri::State<'_, crate::AppState>,
|
||||||
) -> std::result::Result<
|
) -> std::result::Result<std::vec::Vec<crate::DemoWsEndpointPayload>, std::string::String> {
|
||||||
std::vec::Vec<ks_onchain_transport::WsPoolClientSnapshot>,
|
|
||||||
std::string::String,
|
|
||||||
> {
|
|
||||||
return crate::demo_ws_list_pool_clients(state);
|
return crate::demo_ws_list_pool_clients(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,19 @@
|
|||||||
<!-- file: ks-config/CHANGELOG.md -->
|
<!-- file: ks-config/CHANGELOG.md -->
|
||||||
<!-- version: 17 -->
|
<!-- version: 19 -->
|
||||||
|
|
||||||
# CHANGELOG — ks-config
|
# CHANGELOG — ks-config
|
||||||
|
|
||||||
|
## `0.5.1-pre.008`
|
||||||
|
|
||||||
|
- Fix: use `Result::is_err()` for execution and wallet schema validation checks, removing the Clippy redundant-pattern warnings without changing fail-closed behavior.
|
||||||
|
|
||||||
|
- retire `ts-rs` de `ks-config`, supprime ses bindings TypeScript générés et réserve les projections frontend aux DTO des applications propriétaires ;
|
||||||
|
- rend les contrats source/runtime susceptibles de contenir des valeurs résolues non sérialisables et non `Debug` par défaut, et retire les sérialiseurs publics de `AppConfig` ;
|
||||||
|
- ajoute la classification `Secret > Internal > Public`, y compris pour les chaînes composées contenant plusieurs placeholders d'environnement, ainsi qu'une représentation diagnostic générique qui ne révèle jamais les valeurs secret/internal ;
|
||||||
|
- rend la section `application` des compositions opaque pour `ks-config` et fournit un helper générique de validation JSON Schema pour les fragments possédés par les binaires ;
|
||||||
|
- durcit les erreurs de validation/décodage afin de ne plus recopier les valeurs rejetées, notamment pour les URLs et fragments contenant potentiellement des secrets ;
|
||||||
|
- ajoute un test d'API externe et des canaris de non-divulgation pour les helpers de sensibilité.
|
||||||
|
|
||||||
## `0.5.1-pre.007`
|
## `0.5.1-pre.007`
|
||||||
|
|
||||||
- extrait store, wallet et execution vers `config/store.config.json`, `config/wallet.config.json` et `config/execution.config.json`, chacun avec schéma, exemple et `default_profile` ;
|
- extrait store, wallet et execution vers `config/store.config.json`, `config/wallet.config.json` et `config/execution.config.json`, chacun avec schéma, exemple et `default_profile` ;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# file: ks-config/Cargo.toml
|
# file: ks-config/Cargo.toml
|
||||||
# version: 4
|
# version: 5
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "ks-config"
|
name = "ks-config"
|
||||||
@@ -14,7 +14,6 @@ ks-core = { path = "../ks-core" }
|
|||||||
jsonschema.workspace = true
|
jsonschema.workspace = true
|
||||||
serde.workspace = true
|
serde.workspace = true
|
||||||
serde_json.workspace = true
|
serde_json.workspace = true
|
||||||
ts-rs.workspace = true
|
|
||||||
|
|
||||||
[lints]
|
[lints]
|
||||||
workspace = true
|
workspace = true
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<!-- file: ks-config/README.md -->
|
<!-- file: ks-config/README.md -->
|
||||||
<!-- version: 10 -->
|
<!-- version: 11 -->
|
||||||
|
|
||||||
# ks-config
|
# ks-config
|
||||||
|
|
||||||
@@ -46,7 +46,9 @@ Les valeurs globales telles que `logs_directory` et `wallets_directory` ne sont
|
|||||||
- `read_wallet_json_file_with_environment`, `wallet_profile`, `default_wallet_profile` ;
|
- `read_wallet_json_file_with_environment`, `wallet_profile`, `default_wallet_profile` ;
|
||||||
- `read_execution_json_file_with_environment`, `execution_profile`, `default_execution_profile` ;
|
- `read_execution_json_file_with_environment`, `execution_profile`, `default_execution_profile` ;
|
||||||
- `load_workspace_environment`, `resolve_environment_placeholders` ;
|
- `load_workspace_environment`, `resolve_environment_placeholders` ;
|
||||||
- `AppConfig`, `ProfileConfig` pendant la phase de compatibilité.
|
- `classify_environment_variable`, `classify_environment_template`, `diagnostic_environment_value` ;
|
||||||
|
- `validate_json_value_against_schema` pour les fragments possédés par les binaires ;
|
||||||
|
- `AppConfig`, `ProfileConfig` pendant la phase de compatibilité backend-only.
|
||||||
|
|
||||||
## Frontières
|
## Frontières
|
||||||
|
|
||||||
@@ -54,7 +56,9 @@ Les valeurs globales telles que `logs_directory` et `wallets_directory` ne sont
|
|||||||
|
|
||||||
`ks-onchain-transport` peut consommer directement `TransportProfileConfig`.
|
`ks-onchain-transport` peut consommer directement `TransportProfileConfig`.
|
||||||
|
|
||||||
Les dérivations TS-RS des types de `ks-config` sont encore présentes pendant `pre.007`, mais elles ne sont pas considérées comme une frontière durable. L'audit montre que le frontend desktop n'importe pas directement ces bindings ; leur suppression ou réduction est prévue avec les DTO publics sûrs de la prochaine prerelease.
|
Depuis `0.5.1-pre.008`, `ks-config` ne dépend plus de TS-RS et ne produit plus de bindings TypeScript. Ses contrats source/runtime peuvent contenir des secrets résolus : ils ne dérivent donc ni `serde::Serialize` ni `Debug`. Les applications propriétaires construisent leurs DTO publics et diagnostics bornés champ par champ.
|
||||||
|
|
||||||
|
La section `application` d'une composition est volontairement opaque pour `ks-config`. Chaque binaire propriétaire définit son schéma et le valide avec `validate_json_value_against_schema`; le desktop utilise `config/schemas/kb-app-demo-desktop.application.config.schema.json`.
|
||||||
|
|
||||||
## Documents
|
## Documents
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +1,9 @@
|
|||||||
<!-- file: ks-config/TODO.md -->
|
<!-- file: ks-config/TODO.md -->
|
||||||
<!-- version: 9 -->
|
<!-- version: 10 -->
|
||||||
|
|
||||||
# TODO — ks-config
|
# TODO — ks-config
|
||||||
|
|
||||||
## Série `0.5.x`
|
## Série `0.5.x`
|
||||||
|
|
||||||
- [ ] `0.5.1` - appliquer à l’exécution les classes `KS_SECRET_*` / `KB_SECRET_*`, `KS_PUBLIC_*` / `KB_PUBLIC_*` et internes, avec propagation de sensibilité aux valeurs composées.
|
- [ ] `0.5.1-pre.009` - réconcilier une dernière fois schémas, exemples, guide de configuration et contrat d'API externe avant archivage du plan.
|
||||||
- [ ] `0.5.1` - séparer les représentations source, runtime résolue, publique et diagnostic.
|
|
||||||
- [ ] `0.5.1` - interdire qu’un secret résolu soit sérialisé, loggé, inclus dans une erreur ou transmis via Tauri.
|
|
||||||
- [ ] `0.5.1` - supprimer l’exposition frontend de `AppConfig` et `ProfileConfig` résolus complets.
|
|
||||||
- [ ] `0.5.1` - retirer de `ks-config` et réduire dans `ks-lib` les bindings TS-RS qui ne constituent pas un contrat générique indépendant de Tauri ; définir les wrappers publics nécessaires dans `kb-app-demo-desktop`.
|
|
||||||
- [ ] Contrat - maintenir l’identité entre chaque schéma embarqué et son fichier sous `config/schemas/`.
|
- [ ] Contrat - maintenir l’identité entre chaque schéma embarqué et son fichier sous `config/schemas/`.
|
||||||
- [ ] Tests - ajouter les tests d’API externe et les canaris de non-divulgation.
|
|
||||||
- [ ] Documentation - maintenir guides, exemples et `.env.example` avec l’implémentation correspondante.
|
|
||||||
- [ ] Intégration - coordonner les surfaces publiques sûres avec logging, transports, pipeline, scénarios et applications.
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<!-- file: ks-config/USAGE.md -->
|
<!-- file: ks-config/USAGE.md -->
|
||||||
<!-- version: 9 -->
|
<!-- version: 10 -->
|
||||||
|
|
||||||
# Utilisation de ks-config
|
# Utilisation de ks-config
|
||||||
|
|
||||||
@@ -108,6 +108,14 @@ KS_WALLETS_DIRECTORY
|
|||||||
|
|
||||||
Le schéma de ce contrat est `config/schemas/resolved.app.config.schema.json`. Les fixtures correspondantes sont sous `test-fixtures/config/`.
|
Le schéma de ce contrat est `config/schemas/resolved.app.config.schema.json`. Les fixtures correspondantes sont sous `test-fixtures/config/`.
|
||||||
|
|
||||||
|
## Frontière source/runtime/public/diagnostic
|
||||||
|
|
||||||
|
`AppConfig`, `ProfileConfig` et les documents spécialisés chargés avec résolution d'environnement sont des contrats backend-only. Ils peuvent contenir des URLs, DSN, chemins ou autres valeurs sensibles et ne dérivent ni `serde::Serialize` ni `Debug`. `ks-config` n'offre plus de sérialiseur du runtime résolu.
|
||||||
|
|
||||||
|
La sensibilité des variables suit `Secret > Internal > Public`. `classify_environment_template` applique cette règle aux chaînes composées : une URL contenant `${KS_SECRET_HELIUS_API_KEY}` est secrète même si le champ s'appelle simplement `url`. `diagnostic_environment_value` ne retourne jamais une valeur secrète ou interne en clair.
|
||||||
|
|
||||||
|
Les fragments propres à un binaire restent opaques dans `CompositionProfileConfig.application`. Le propriétaire les valide avec `validate_json_value_against_schema` et son schéma dédié.
|
||||||
|
|
||||||
## Frontière TypeScript
|
## Frontière TypeScript
|
||||||
|
|
||||||
Les bindings TS-RS générés depuis `ks-config` ne sont pas importés directement par le frontend desktop actuel. Ils sont donc considérés comme transitoires jusqu'à la prochaine prerelease, qui introduira les DTO publics/diagnostiques et supprimera les exports TypeScript non justifiés des crates généralistes.
|
`ks-config` ne dépend plus de TS-RS et ne génère aucun binding TypeScript. Les types traversant Tauri sont définis comme DTO/wrappers dans l'application propriétaire ; `kb-app-demo-desktop` construit notamment ses projections de configuration publique et diagnostic sans sérialiser `AppConfig/ProfileConfig`.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// file: ks-config/src/composition.rs
|
// file: ks-config/src/composition.rs
|
||||||
// version: 2
|
// version: 3
|
||||||
|
|
||||||
//! Binary composition configuration and resolution into the shared runtime profile contract.
|
//! Binary composition configuration and resolution into the shared runtime profile contract.
|
||||||
|
|
||||||
@@ -13,7 +13,7 @@ const DEFAULT_WALLET_CONFIG_PATH: &str = "config/wallet.config.json";
|
|||||||
const DEFAULT_EXECUTION_CONFIG_PATH: &str = "config/execution.config.json";
|
const DEFAULT_EXECUTION_CONFIG_PATH: &str = "config/execution.config.json";
|
||||||
|
|
||||||
/// Root composition document used by a binary to select shared configuration profiles.
|
/// Root composition document used by a binary to select shared configuration profiles.
|
||||||
#[derive(Clone, Debug, serde::Deserialize, Eq, PartialEq, serde::Serialize)]
|
#[derive(Clone, serde::Deserialize, Eq, PartialEq)]
|
||||||
pub struct CompositionConfigDocument {
|
pub struct CompositionConfigDocument {
|
||||||
/// Active binary composition profile name.
|
/// Active binary composition profile name.
|
||||||
pub active_profile: std::string::String,
|
pub active_profile: std::string::String,
|
||||||
@@ -24,7 +24,7 @@ pub struct CompositionConfigDocument {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Paths of shared configuration documents consumed by one binary composition.
|
/// Paths of shared configuration documents consumed by one binary composition.
|
||||||
#[derive(Clone, Debug, serde::Deserialize, Eq, PartialEq, serde::Serialize)]
|
#[derive(Clone, serde::Deserialize, Eq, PartialEq)]
|
||||||
pub struct CompositionConfigSources {
|
pub struct CompositionConfigSources {
|
||||||
/// Logging configuration document path relative to the workspace root unless absolute.
|
/// Logging configuration document path relative to the workspace root unless absolute.
|
||||||
pub logging: std::string::String,
|
pub logging: std::string::String,
|
||||||
@@ -41,12 +41,12 @@ pub struct CompositionConfigSources {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Named composition profile with optional overrides of each shared document default.
|
/// Named composition profile with optional overrides of each shared document default.
|
||||||
#[derive(Clone, Debug, serde::Deserialize, Eq, PartialEq, serde::Serialize)]
|
#[derive(Clone, serde::Deserialize, Eq, PartialEq)]
|
||||||
pub struct CompositionProfileConfig {
|
pub struct CompositionProfileConfig {
|
||||||
/// Composition profile code.
|
/// Composition profile code.
|
||||||
pub name: std::string::String,
|
pub name: std::string::String,
|
||||||
/// Application metadata retained until the application-specific split is completed.
|
/// Optional binary-owned application settings opaque to the shared composition layer.
|
||||||
pub app: crate::AppSectionConfig,
|
pub application: std::option::Option<serde_json::Value>,
|
||||||
/// Optional logging profile override.
|
/// Optional logging profile override.
|
||||||
pub logging_profile: std::option::Option<std::string::String>,
|
pub logging_profile: std::option::Option<std::string::String>,
|
||||||
/// Optional transport profile override.
|
/// Optional transport profile override.
|
||||||
@@ -59,12 +59,10 @@ pub struct CompositionProfileConfig {
|
|||||||
pub wallet_profile: std::option::Option<std::string::String>,
|
pub wallet_profile: std::option::Option<std::string::String>,
|
||||||
/// Optional execution profile override.
|
/// Optional execution profile override.
|
||||||
pub execution_profile: std::option::Option<std::string::String>,
|
pub execution_profile: std::option::Option<std::string::String>,
|
||||||
/// Desktop demo flags retained until the application-specific split is completed.
|
|
||||||
pub demo: crate::DemoConfig,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Resolved application configuration and the source documents needed by a binary.
|
/// Resolved application configuration and the source documents needed by a binary.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Eq, PartialEq)]
|
||||||
pub struct ComposedAppConfig {
|
pub struct ComposedAppConfig {
|
||||||
/// Parsed binary composition document.
|
/// Parsed binary composition document.
|
||||||
pub composition: CompositionConfigDocument,
|
pub composition: CompositionConfigDocument,
|
||||||
@@ -127,9 +125,9 @@ pub fn validate_composition_json_schema(raw_json: &str) -> ks_core::Result<()> {
|
|||||||
};
|
};
|
||||||
return match validator.validate(&instance) {
|
return match validator.validate(&instance) {
|
||||||
std::result::Result::Ok(()) => std::result::Result::Ok(()),
|
std::result::Result::Ok(()) => std::result::Result::Ok(()),
|
||||||
std::result::Result::Err(error) => std::result::Result::Err(ks_core::Error::new(
|
std::result::Result::Err(_) => std::result::Result::Err(ks_core::Error::new(
|
||||||
"composition_config_schema_validation_failed",
|
"composition_config_schema_validation_failed",
|
||||||
error.to_string(),
|
"composition configuration does not satisfy its schema",
|
||||||
)),
|
)),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -142,10 +140,10 @@ pub fn parse_composition_json(raw_json: &str) -> ks_core::Result<CompositionConf
|
|||||||
}
|
}
|
||||||
let document = match serde_json::from_str::<CompositionConfigDocument>(raw_json) {
|
let document = match serde_json::from_str::<CompositionConfigDocument>(raw_json) {
|
||||||
std::result::Result::Ok(value) => value,
|
std::result::Result::Ok(value) => value,
|
||||||
std::result::Result::Err(error) => {
|
std::result::Result::Err(_) => {
|
||||||
return std::result::Result::Err(ks_core::Error::new(
|
return std::result::Result::Err(ks_core::Error::new(
|
||||||
"composition_config_json_decode_failed",
|
"composition_config_json_decode_failed",
|
||||||
error.to_string(),
|
"composition configuration could not be decoded",
|
||||||
));
|
));
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -291,7 +289,6 @@ pub fn compose_app_config(
|
|||||||
};
|
};
|
||||||
profiles.push(crate::ProfileConfig {
|
profiles.push(crate::ProfileConfig {
|
||||||
name: profile.name.clone(),
|
name: profile.name.clone(),
|
||||||
app: profile.app.clone(),
|
|
||||||
database: store_profile.database.clone(),
|
database: store_profile.database.clone(),
|
||||||
solana: crate::SolanaConfig {
|
solana: crate::SolanaConfig {
|
||||||
http_endpoints: transport_profile.http_endpoints,
|
http_endpoints: transport_profile.http_endpoints,
|
||||||
@@ -300,7 +297,6 @@ pub fn compose_app_config(
|
|||||||
},
|
},
|
||||||
wallet: wallet_profile,
|
wallet: wallet_profile,
|
||||||
execution: execution_profile.config.clone(),
|
execution: execution_profile.config.clone(),
|
||||||
demo: profile.demo.clone(),
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
let config = crate::AppConfig {
|
let config = crate::AppConfig {
|
||||||
@@ -437,20 +433,13 @@ pub fn read_default_shared_app_config_with_environment(
|
|||||||
},
|
},
|
||||||
profiles: vec![CompositionProfileConfig {
|
profiles: vec![CompositionProfileConfig {
|
||||||
name: profile_name.clone(),
|
name: profile_name.clone(),
|
||||||
app: crate::AppSectionConfig {
|
application: std::option::Option::None,
|
||||||
name: "khadhroony-solana".to_string(),
|
|
||||||
environment: profile_name,
|
|
||||||
},
|
|
||||||
logging_profile: std::option::Option::None,
|
logging_profile: std::option::Option::None,
|
||||||
transport_profile: std::option::Option::None,
|
transport_profile: std::option::Option::None,
|
||||||
listeners_profile: std::option::Option::None,
|
listeners_profile: std::option::Option::None,
|
||||||
store_profile: std::option::Option::None,
|
store_profile: std::option::Option::None,
|
||||||
wallet_profile: std::option::Option::None,
|
wallet_profile: std::option::Option::None,
|
||||||
execution_profile: std::option::Option::None,
|
execution_profile: std::option::Option::None,
|
||||||
demo: crate::DemoConfig {
|
|
||||||
live_demo_enabled: false,
|
|
||||||
trading_demo_enabled: false,
|
|
||||||
},
|
|
||||||
}],
|
}],
|
||||||
};
|
};
|
||||||
return compose_app_config(&composition, &transport, &listeners, &store, &wallet, &execution);
|
return compose_app_config(&composition, &transport, &listeners, &store, &wallet, &execution);
|
||||||
@@ -593,7 +582,7 @@ mod tests {
|
|||||||
const DEFAULT_COMPOSITION: &str =
|
const DEFAULT_COMPOSITION: &str =
|
||||||
include_str!("../../config/kb-app-demo-desktop.default.config.json");
|
include_str!("../../config/kb-app-demo-desktop.default.config.json");
|
||||||
const EXAMPLE_COMPOSITION: &str =
|
const EXAMPLE_COMPOSITION: &str =
|
||||||
include_str!("../../config/example.kb-app-demo-desktop.default.config.json");
|
include_str!("../../config/exemples/example.kb-app-demo-desktop.default.config.json");
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn default_and_example_compositions_validate() {
|
fn default_and_example_compositions_validate() {
|
||||||
@@ -613,6 +602,7 @@ mod tests {
|
|||||||
panic!("local Devnet composition must resolve: {error}")
|
panic!("local Devnet composition must resolve: {error}")
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
assert!(profile.application.is_some());
|
||||||
assert!(profile.logging_profile.is_none());
|
assert!(profile.logging_profile.is_none());
|
||||||
assert!(profile.transport_profile.is_none());
|
assert!(profile.transport_profile.is_none());
|
||||||
assert!(profile.store_profile.is_none());
|
assert!(profile.store_profile.is_none());
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// file: ks-config/src/environment.rs
|
// file: ks-config/src/environment.rs
|
||||||
// version: 5
|
// version: 6
|
||||||
|
|
||||||
//! Environment-file loading and configuration placeholder resolution.
|
//! Environment-file loading and configuration placeholder resolution.
|
||||||
|
|
||||||
@@ -32,9 +32,9 @@ pub fn load_workspace_environment(
|
|||||||
std::result::Result::Ok(()) => std::result::Result::Ok(EnvironmentLoadReport {
|
std::result::Result::Ok(()) => std::result::Result::Ok(EnvironmentLoadReport {
|
||||||
loaded_path: std::option::Option::Some(selected_path),
|
loaded_path: std::option::Option::Some(selected_path),
|
||||||
}),
|
}),
|
||||||
std::result::Result::Err(error) => std::result::Result::Err(ks_core::Error::new(
|
std::result::Result::Err(_) => std::result::Result::Err(ks_core::Error::new(
|
||||||
"config_env_file_load_failed",
|
"config_env_file_load_failed",
|
||||||
format!("{}: {error}", selected_path.display()),
|
format!("failed to load environment file {}", selected_path.display()),
|
||||||
)),
|
)),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// file: ks-config/src/execution.rs
|
// file: ks-config/src/execution.rs
|
||||||
// version: 1
|
// version: 3
|
||||||
|
|
||||||
//! Independent execution policy configuration document loading and validation.
|
//! Independent execution policy configuration document loading and validation.
|
||||||
|
|
||||||
@@ -7,7 +7,7 @@ const EXECUTION_JSON_SCHEMA: &str =
|
|||||||
include_str!("../../config/schemas/execution.config.schema.json");
|
include_str!("../../config/schemas/execution.config.schema.json");
|
||||||
|
|
||||||
/// Root execution policy document with one default profile and named alternatives.
|
/// Root execution policy document with one default profile and named alternatives.
|
||||||
#[derive(Clone, Debug, serde::Deserialize, Eq, PartialEq, serde::Serialize)]
|
#[derive(Clone, serde::Deserialize, Eq, PartialEq)]
|
||||||
pub struct ExecutionConfigDocument {
|
pub struct ExecutionConfigDocument {
|
||||||
/// Default execution profile used when a composition does not override it.
|
/// Default execution profile used when a composition does not override it.
|
||||||
pub default_profile: std::string::String,
|
pub default_profile: std::string::String,
|
||||||
@@ -16,7 +16,7 @@ pub struct ExecutionConfigDocument {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Named execution policy profile.
|
/// Named execution policy profile.
|
||||||
#[derive(Clone, Debug, serde::Deserialize, Eq, PartialEq, serde::Serialize)]
|
#[derive(Clone, serde::Deserialize, Eq, PartialEq)]
|
||||||
pub struct ExecutionProfileConfig {
|
pub struct ExecutionProfileConfig {
|
||||||
/// Profile code.
|
/// Profile code.
|
||||||
pub name: std::string::String,
|
pub name: std::string::String,
|
||||||
@@ -59,18 +59,18 @@ pub fn parse_execution_json(raw_json: &str) -> ks_core::Result<ExecutionConfigDo
|
|||||||
));
|
));
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
if let std::result::Result::Err(error) = validator.validate(&instance) {
|
if validator.validate(&instance).is_err() {
|
||||||
return std::result::Result::Err(ks_core::Error::new(
|
return std::result::Result::Err(ks_core::Error::new(
|
||||||
"execution_config_schema_validation_failed",
|
"execution_config_schema_validation_failed",
|
||||||
error.to_string(),
|
"execution configuration does not satisfy its schema",
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
let document = match serde_json::from_str::<ExecutionConfigDocument>(raw_json) {
|
let document = match serde_json::from_str::<ExecutionConfigDocument>(raw_json) {
|
||||||
std::result::Result::Ok(value) => value,
|
std::result::Result::Ok(value) => value,
|
||||||
std::result::Result::Err(error) => {
|
std::result::Result::Err(_) => {
|
||||||
return std::result::Result::Err(ks_core::Error::new(
|
return std::result::Result::Err(ks_core::Error::new(
|
||||||
"execution_config_json_decode_failed",
|
"execution_config_json_decode_failed",
|
||||||
error.to_string(),
|
"execution configuration could not be decoded",
|
||||||
));
|
));
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -162,7 +162,8 @@ pub fn validate_execution_document(document: &ExecutionConfigDocument) -> ks_cor
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
const DEFAULT_EXECUTION: &str = include_str!("../../config/execution.config.json");
|
const DEFAULT_EXECUTION: &str = include_str!("../../config/execution.config.json");
|
||||||
const EXAMPLE_EXECUTION: &str = include_str!("../../config/example.execution.config.json");
|
const EXAMPLE_EXECUTION: &str =
|
||||||
|
include_str!("../../config/exemples/example.execution.config.json");
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn default_and_example_execution_configs_validate() {
|
fn default_and_example_execution_configs_validate() {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// file: ks-config/src/lib.rs
|
// file: ks-config/src/lib.rs
|
||||||
// version: 8
|
// version: 9
|
||||||
|
|
||||||
//! Khadhroony Solana shared configuration contracts and composition helpers.
|
//! Khadhroony Solana shared configuration contracts and composition helpers.
|
||||||
#![warn(missing_docs)]
|
#![warn(missing_docs)]
|
||||||
@@ -10,6 +10,8 @@ mod composition;
|
|||||||
mod environment;
|
mod environment;
|
||||||
mod execution;
|
mod execution;
|
||||||
mod listeners;
|
mod listeners;
|
||||||
|
mod schema;
|
||||||
|
mod sensitivity;
|
||||||
mod settings;
|
mod settings;
|
||||||
mod store;
|
mod store;
|
||||||
mod transport;
|
mod transport;
|
||||||
@@ -97,16 +99,22 @@ pub use self::listeners::resolved_listener_config;
|
|||||||
pub use self::listeners::validate_listeners_document;
|
pub use self::listeners::validate_listeners_document;
|
||||||
/// Exposes listener JSON Schema validation.
|
/// Exposes listener JSON Schema validation.
|
||||||
pub use self::listeners::validate_listeners_json_schema;
|
pub use self::listeners::validate_listeners_json_schema;
|
||||||
|
/// Exposes generic caller-owned JSON Schema validation.
|
||||||
|
pub use self::schema::validate_json_value_against_schema;
|
||||||
|
/// Exposes Khadhroony environment-value sensitivity classification.
|
||||||
|
pub use self::sensitivity::EnvironmentValueSensitivity;
|
||||||
|
/// Exposes composed-value environment-placeholder sensitivity classification.
|
||||||
|
pub use self::sensitivity::classify_environment_template;
|
||||||
|
/// Exposes Khadhroony environment-variable namespace classification.
|
||||||
|
pub use self::sensitivity::classify_environment_variable;
|
||||||
|
/// Exposes the bounded generic diagnostic representation for an environment value.
|
||||||
|
pub use self::sensitivity::diagnostic_environment_value;
|
||||||
/// Exposes the account listener configuration type.
|
/// Exposes the account listener configuration type.
|
||||||
pub use self::settings::AccountListenerConfig;
|
pub use self::settings::AccountListenerConfig;
|
||||||
/// Exposes the root resolved runtime configuration type.
|
/// Exposes the root resolved runtime configuration type.
|
||||||
pub use self::settings::AppConfig;
|
pub use self::settings::AppConfig;
|
||||||
/// Exposes the application metadata configuration type.
|
|
||||||
pub use self::settings::AppSectionConfig;
|
|
||||||
/// Exposes the database configuration type.
|
/// Exposes the database configuration type.
|
||||||
pub use self::settings::DatabaseConfig;
|
pub use self::settings::DatabaseConfig;
|
||||||
/// Exposes the temporary demo application configuration type.
|
|
||||||
pub use self::settings::DemoConfig;
|
|
||||||
/// Exposes the endpoint role configuration type.
|
/// Exposes the endpoint role configuration type.
|
||||||
pub use self::settings::EndpointRoleConfig;
|
pub use self::settings::EndpointRoleConfig;
|
||||||
/// Exposes the execution configuration type.
|
/// Exposes the execution configuration type.
|
||||||
@@ -143,10 +151,6 @@ pub use self::settings::parse_config_json;
|
|||||||
pub use self::settings::read_config_json_file;
|
pub use self::settings::read_config_json_file;
|
||||||
/// Exposes resolved runtime snapshot loading with workspace environment resolution.
|
/// Exposes resolved runtime snapshot loading with workspace environment resolution.
|
||||||
pub use self::settings::read_config_json_file_with_environment;
|
pub use self::settings::read_config_json_file_with_environment;
|
||||||
/// Exposes the compact JSON serializer for resolved runtime configuration values.
|
|
||||||
pub use self::settings::serialize_config_json;
|
|
||||||
/// Exposes the pretty JSON serializer for resolved runtime configuration values.
|
|
||||||
pub use self::settings::serialize_config_json_pretty;
|
|
||||||
/// Exposes the typed resolved runtime configuration validator.
|
/// Exposes the typed resolved runtime configuration validator.
|
||||||
pub use self::settings::validate_config;
|
pub use self::settings::validate_config;
|
||||||
/// Exposes the JSON Schema validator for raw resolved runtime configuration JSON.
|
/// Exposes the JSON Schema validator for raw resolved runtime configuration JSON.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// file: ks-config/src/listeners.rs
|
// file: ks-config/src/listeners.rs
|
||||||
// version: 2
|
// version: 3
|
||||||
|
|
||||||
//! Independent Solana listener configuration document loading and validation.
|
//! Independent Solana listener configuration document loading and validation.
|
||||||
|
|
||||||
@@ -7,7 +7,7 @@ const LISTENERS_JSON_SCHEMA: &str =
|
|||||||
include_str!("../../config/schemas/listeners.config.schema.json");
|
include_str!("../../config/schemas/listeners.config.schema.json");
|
||||||
|
|
||||||
/// Root listener document containing independently selectable named profiles.
|
/// Root listener document containing independently selectable named profiles.
|
||||||
#[derive(Clone, Debug, serde::Deserialize, Eq, PartialEq, serde::Serialize)]
|
#[derive(Clone, serde::Deserialize, Eq, PartialEq)]
|
||||||
pub struct ListenersConfigDocument {
|
pub struct ListenersConfigDocument {
|
||||||
/// Default listener profile used by consumers that do not provide an explicit selection.
|
/// Default listener profile used by consumers that do not provide an explicit selection.
|
||||||
pub default_profile: std::string::String,
|
pub default_profile: std::string::String,
|
||||||
@@ -16,7 +16,7 @@ pub struct ListenersConfigDocument {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Named listener profile.
|
/// Named listener profile.
|
||||||
#[derive(Clone, Debug, serde::Deserialize, Eq, PartialEq, serde::Serialize)]
|
#[derive(Clone, serde::Deserialize, Eq, PartialEq)]
|
||||||
pub struct ListenersProfileConfig {
|
pub struct ListenersProfileConfig {
|
||||||
/// Profile code.
|
/// Profile code.
|
||||||
pub name: std::string::String,
|
pub name: std::string::String,
|
||||||
@@ -75,9 +75,9 @@ pub fn validate_listeners_json_schema(raw_json: &str) -> ks_core::Result<()> {
|
|||||||
};
|
};
|
||||||
return match validator.validate(&instance) {
|
return match validator.validate(&instance) {
|
||||||
std::result::Result::Ok(()) => std::result::Result::Ok(()),
|
std::result::Result::Ok(()) => std::result::Result::Ok(()),
|
||||||
std::result::Result::Err(error) => std::result::Result::Err(ks_core::Error::new(
|
std::result::Result::Err(_) => std::result::Result::Err(ks_core::Error::new(
|
||||||
"listeners_config_schema_validation_failed",
|
"listeners_config_schema_validation_failed",
|
||||||
error.to_string(),
|
"listeners configuration does not satisfy its schema",
|
||||||
)),
|
)),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -90,10 +90,10 @@ pub fn parse_listeners_json(raw_json: &str) -> ks_core::Result<ListenersConfigDo
|
|||||||
}
|
}
|
||||||
let document = match serde_json::from_str::<ListenersConfigDocument>(raw_json) {
|
let document = match serde_json::from_str::<ListenersConfigDocument>(raw_json) {
|
||||||
std::result::Result::Ok(document) => document,
|
std::result::Result::Ok(document) => document,
|
||||||
std::result::Result::Err(error) => {
|
std::result::Result::Err(_) => {
|
||||||
return std::result::Result::Err(ks_core::Error::new(
|
return std::result::Result::Err(ks_core::Error::new(
|
||||||
"listeners_config_json_decode_failed",
|
"listeners_config_json_decode_failed",
|
||||||
error.to_string(),
|
"listeners configuration could not be decoded",
|
||||||
));
|
));
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -214,7 +214,8 @@ pub fn validate_listeners_document(document: &ListenersConfigDocument) -> ks_cor
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
const DEFAULT_LISTENERS: &str = include_str!("../../config/listeners.config.json");
|
const DEFAULT_LISTENERS: &str = include_str!("../../config/listeners.config.json");
|
||||||
const EXAMPLE_LISTENERS: &str = include_str!("../../config/example.listeners.config.json");
|
const EXAMPLE_LISTENERS: &str =
|
||||||
|
include_str!("../../config/exemples/example.listeners.config.json");
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn default_and_example_listener_configs_validate() {
|
fn default_and_example_listener_configs_validate() {
|
||||||
|
|||||||
56
ks-config/src/schema.rs
Normal file
56
ks-config/src/schema.rs
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
// file: ks-config/src/schema.rs
|
||||||
|
// version: 1
|
||||||
|
|
||||||
|
//! Generic JSON Schema validation helpers for binary-owned configuration fragments.
|
||||||
|
|
||||||
|
/// Validates one JSON value against caller-owned JSON Schema text without echoing instance values.
|
||||||
|
pub fn validate_json_value_against_schema(
|
||||||
|
schema_json: &str,
|
||||||
|
instance: &serde_json::Value,
|
||||||
|
validation_error_code: &str,
|
||||||
|
) -> ks_core::Result<()> {
|
||||||
|
let schema = match serde_json::from_str::<serde_json::Value>(schema_json) {
|
||||||
|
std::result::Result::Ok(value) => value,
|
||||||
|
std::result::Result::Err(error) => {
|
||||||
|
return std::result::Result::Err(ks_core::Error::new(
|
||||||
|
"config_fragment_schema_parse_failed",
|
||||||
|
error.to_string(),
|
||||||
|
));
|
||||||
|
},
|
||||||
|
};
|
||||||
|
let validator = match jsonschema::validator_for(&schema) {
|
||||||
|
std::result::Result::Ok(value) => value,
|
||||||
|
std::result::Result::Err(error) => {
|
||||||
|
return std::result::Result::Err(ks_core::Error::new(
|
||||||
|
"config_fragment_schema_compile_failed",
|
||||||
|
error.to_string(),
|
||||||
|
));
|
||||||
|
},
|
||||||
|
};
|
||||||
|
return match validator.validate(instance) {
|
||||||
|
std::result::Result::Ok(()) => std::result::Result::Ok(()),
|
||||||
|
std::result::Result::Err(_) => std::result::Result::Err(ks_core::Error::new(
|
||||||
|
validation_error_code,
|
||||||
|
"configuration fragment does not satisfy its schema",
|
||||||
|
)),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
#[test]
|
||||||
|
fn validation_error_never_echoes_instance_secret() {
|
||||||
|
let schema = r#"{"type":"object","additionalProperties":false,"required":["value"],"properties":{"value":{"type":"integer"}}}"#;
|
||||||
|
let instance = serde_json::json!({"value": "SECRET-CANARY"});
|
||||||
|
let result = super::validate_json_value_against_schema(
|
||||||
|
schema,
|
||||||
|
&instance,
|
||||||
|
"test_fragment_validation_failed",
|
||||||
|
);
|
||||||
|
let error = match result {
|
||||||
|
std::result::Result::Ok(()) => panic!("invalid fragment must fail"),
|
||||||
|
std::result::Result::Err(error) => error,
|
||||||
|
};
|
||||||
|
assert!(!error.to_string().contains("SECRET-CANARY"));
|
||||||
|
}
|
||||||
|
}
|
||||||
160
ks-config/src/sensitivity.rs
Normal file
160
ks-config/src/sensitivity.rs
Normal file
@@ -0,0 +1,160 @@
|
|||||||
|
// file: ks-config/src/sensitivity.rs
|
||||||
|
// version: 1
|
||||||
|
|
||||||
|
//! Application environment-variable sensitivity classification.
|
||||||
|
|
||||||
|
/// Sensitivity assigned to one Khadhroony-owned environment value.
|
||||||
|
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||||
|
pub enum EnvironmentValueSensitivity {
|
||||||
|
/// Secret value that must never cross logs, diagnostics, serialization or UI boundaries.
|
||||||
|
Secret,
|
||||||
|
/// Internal value that is hidden by default and may appear only through an explicit bounded diagnostic.
|
||||||
|
Internal,
|
||||||
|
/// Value explicitly classified as eligible for a public DTO.
|
||||||
|
Public,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Classifies every Khadhroony environment placeholder contained in arbitrary text.
|
||||||
|
///
|
||||||
|
/// The returned sensitivity follows `Secret > Internal > Public`, so an endpoint URL that embeds
|
||||||
|
/// one `KS_SECRET_*` placeholder is classified as secret even when the surrounding URL is public.
|
||||||
|
pub fn classify_environment_template(
|
||||||
|
raw: &str,
|
||||||
|
) -> std::option::Option<EnvironmentValueSensitivity> {
|
||||||
|
let bytes = raw.as_bytes();
|
||||||
|
let mut sensitivity = std::option::Option::None;
|
||||||
|
let mut index = 0_usize;
|
||||||
|
while index < bytes.len() {
|
||||||
|
if bytes[index] == b'$' && index + 1 < bytes.len() && bytes[index + 1] == b'{' {
|
||||||
|
let mut end = index + 2;
|
||||||
|
while end < bytes.len() && bytes[end] != b'}' {
|
||||||
|
end += 1;
|
||||||
|
}
|
||||||
|
if end < bytes.len() {
|
||||||
|
let expression = &raw[index + 2..end];
|
||||||
|
let name = match expression.split_once(":-") {
|
||||||
|
std::option::Option::Some((name, _)) => name,
|
||||||
|
std::option::Option::None => expression,
|
||||||
|
};
|
||||||
|
sensitivity = merge_sensitivity(sensitivity, classify_environment_variable(name));
|
||||||
|
index = end + 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
index += 1;
|
||||||
|
}
|
||||||
|
return sensitivity;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Classifies a Khadhroony-owned environment variable by its namespace.
|
||||||
|
pub fn classify_environment_variable(
|
||||||
|
name: &str,
|
||||||
|
) -> std::option::Option<EnvironmentValueSensitivity> {
|
||||||
|
if name.starts_with("KS_SECRET_") || name.starts_with("KB_SECRET_") {
|
||||||
|
return std::option::Option::Some(EnvironmentValueSensitivity::Secret);
|
||||||
|
}
|
||||||
|
if name.starts_with("KS_PUBLIC_") || name.starts_with("KB_PUBLIC_") {
|
||||||
|
return std::option::Option::Some(EnvironmentValueSensitivity::Public);
|
||||||
|
}
|
||||||
|
if name.starts_with("KS_") || name.starts_with("KB_") {
|
||||||
|
return std::option::Option::Some(EnvironmentValueSensitivity::Internal);
|
||||||
|
}
|
||||||
|
return std::option::Option::None;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Produces the generic diagnostic representation allowed for one environment value.
|
||||||
|
pub fn diagnostic_environment_value(
|
||||||
|
name: &str,
|
||||||
|
value: &str,
|
||||||
|
) -> std::option::Option<std::string::String> {
|
||||||
|
return match classify_environment_variable(name) {
|
||||||
|
std::option::Option::Some(EnvironmentValueSensitivity::Secret) => {
|
||||||
|
std::option::Option::Some("<redacted>".to_string())
|
||||||
|
},
|
||||||
|
std::option::Option::Some(EnvironmentValueSensitivity::Internal) => {
|
||||||
|
std::option::Option::Some("<configured>".to_string())
|
||||||
|
},
|
||||||
|
std::option::Option::Some(EnvironmentValueSensitivity::Public) => {
|
||||||
|
std::option::Option::Some(value.to_string())
|
||||||
|
},
|
||||||
|
std::option::Option::None => std::option::Option::None,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn merge_sensitivity(
|
||||||
|
left: std::option::Option<EnvironmentValueSensitivity>,
|
||||||
|
right: std::option::Option<EnvironmentValueSensitivity>,
|
||||||
|
) -> std::option::Option<EnvironmentValueSensitivity> {
|
||||||
|
if left == std::option::Option::Some(EnvironmentValueSensitivity::Secret)
|
||||||
|
|| right == std::option::Option::Some(EnvironmentValueSensitivity::Secret)
|
||||||
|
{
|
||||||
|
return std::option::Option::Some(EnvironmentValueSensitivity::Secret);
|
||||||
|
}
|
||||||
|
if left == std::option::Option::Some(EnvironmentValueSensitivity::Internal)
|
||||||
|
|| right == std::option::Option::Some(EnvironmentValueSensitivity::Internal)
|
||||||
|
{
|
||||||
|
return std::option::Option::Some(EnvironmentValueSensitivity::Internal);
|
||||||
|
}
|
||||||
|
if left == std::option::Option::Some(EnvironmentValueSensitivity::Public)
|
||||||
|
|| right == std::option::Option::Some(EnvironmentValueSensitivity::Public)
|
||||||
|
{
|
||||||
|
return std::option::Option::Some(EnvironmentValueSensitivity::Public);
|
||||||
|
}
|
||||||
|
return std::option::Option::None;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
#[test]
|
||||||
|
fn composed_values_inherit_the_strongest_placeholder_sensitivity() {
|
||||||
|
assert_eq!(
|
||||||
|
super::classify_environment_template(
|
||||||
|
"https://rpc.invalid/?api-key=${KS_SECRET_HELIUS_API_KEY}&mint=${KS_PUBLIC_DEVNET_TOKEN_2022_MINT}"
|
||||||
|
),
|
||||||
|
std::option::Option::Some(super::EnvironmentValueSensitivity::Secret)
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
super::classify_environment_template(
|
||||||
|
"${KS_LOGS_DIRECTORY:-logs}/${KS_PUBLIC_SPL_TOKEN_PROGRAM_ID}"
|
||||||
|
),
|
||||||
|
std::option::Option::Some(super::EnvironmentValueSensitivity::Internal)
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
super::classify_environment_template("${KS_PUBLIC_SPL_TOKEN_PROGRAM_ID}"),
|
||||||
|
std::option::Option::Some(super::EnvironmentValueSensitivity::Public)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn generic_diagnostic_never_reveals_secret_or_internal_values() {
|
||||||
|
assert_eq!(
|
||||||
|
super::diagnostic_environment_value("KS_SECRET_HELIUS_API_KEY", "SECRET-CANARY"),
|
||||||
|
std::option::Option::Some("<redacted>".to_string())
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
super::diagnostic_environment_value("KS_LOGS_DIRECTORY", "/private/logs"),
|
||||||
|
std::option::Option::Some("<configured>".to_string())
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
super::diagnostic_environment_value("KS_PUBLIC_SPL_TOKEN_PROGRAM_ID", "Token111"),
|
||||||
|
std::option::Option::Some("Token111".to_string())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn namespaces_map_to_secret_internal_and_public() {
|
||||||
|
assert_eq!(
|
||||||
|
super::classify_environment_variable("KS_SECRET_HELIUS_API_KEY"),
|
||||||
|
std::option::Option::Some(super::EnvironmentValueSensitivity::Secret)
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
super::classify_environment_variable("KS_LOGS_DIRECTORY"),
|
||||||
|
std::option::Option::Some(super::EnvironmentValueSensitivity::Internal)
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
super::classify_environment_variable("KB_PUBLIC_DEMO_VALUE"),
|
||||||
|
std::option::Option::Some(super::EnvironmentValueSensitivity::Public)
|
||||||
|
);
|
||||||
|
assert_eq!(super::classify_environment_variable("HOME"), std::option::Option::None);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,16 +1,13 @@
|
|||||||
// file: ks-config/src/settings.rs
|
// file: ks-config/src/settings.rs
|
||||||
// version: 22
|
// version: 23
|
||||||
|
|
||||||
//! Resolved runtime configuration models retained during the `0.5.1` source-document split.
|
//! Resolved runtime configuration models retained during the `0.5.1` source-document split.
|
||||||
|
|
||||||
use ts_rs::TS; // rust-rules: derive-import
|
|
||||||
|
|
||||||
const CONFIG_JSON_SCHEMA: &str =
|
const CONFIG_JSON_SCHEMA: &str =
|
||||||
include_str!("../../config/schemas/resolved.app.config.schema.json");
|
include_str!("../../config/schemas/resolved.app.config.schema.json");
|
||||||
|
|
||||||
/// Resolved runtime configuration containing every composed named profile.
|
/// Resolved runtime configuration containing every composed named profile.
|
||||||
#[derive(Clone, Debug, serde::Deserialize, Eq, PartialEq, serde::Serialize, TS)]
|
#[derive(Clone, serde::Deserialize, Eq, PartialEq)]
|
||||||
#[ts(export, export_to = "../frontend/ts/bindings/ks_config/settings/AppConfig.ts")]
|
|
||||||
pub struct AppConfig {
|
pub struct AppConfig {
|
||||||
/// Active profile name.
|
/// Active profile name.
|
||||||
pub active_profile: std::string::String,
|
pub active_profile: std::string::String,
|
||||||
@@ -19,16 +16,10 @@ pub struct AppConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Resolved runtime profile selected by the root active profile name.
|
/// Resolved runtime profile selected by the root active profile name.
|
||||||
#[derive(Clone, Debug, serde::Deserialize, Eq, PartialEq, serde::Serialize, TS)]
|
#[derive(Clone, serde::Deserialize, Eq, PartialEq)]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_config/settings/ProfileConfig.ts"
|
|
||||||
)]
|
|
||||||
pub struct ProfileConfig {
|
pub struct ProfileConfig {
|
||||||
/// Profile code.
|
/// Profile code.
|
||||||
pub name: std::string::String,
|
pub name: std::string::String,
|
||||||
/// Application metadata.
|
|
||||||
pub app: AppSectionConfig,
|
|
||||||
/// Database configuration.
|
/// Database configuration.
|
||||||
pub database: DatabaseConfig,
|
pub database: DatabaseConfig,
|
||||||
/// Solana endpoint and listener configuration.
|
/// Solana endpoint and listener configuration.
|
||||||
@@ -37,29 +28,10 @@ pub struct ProfileConfig {
|
|||||||
pub wallet: WalletConfig,
|
pub wallet: WalletConfig,
|
||||||
/// Execution safety configuration.
|
/// Execution safety configuration.
|
||||||
pub execution: ExecutionConfig,
|
pub execution: ExecutionConfig,
|
||||||
/// Demo application configuration.
|
|
||||||
pub demo: DemoConfig,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Application metadata for a profile.
|
|
||||||
#[derive(Clone, Debug, serde::Deserialize, Eq, PartialEq, serde::Serialize, TS)]
|
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_config/settings/AppSectionConfig.ts"
|
|
||||||
)]
|
|
||||||
pub struct AppSectionConfig {
|
|
||||||
/// Application name.
|
|
||||||
pub name: std::string::String,
|
|
||||||
/// Environment name.
|
|
||||||
pub environment: std::string::String,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Database backend configuration.
|
/// Database backend configuration.
|
||||||
#[derive(Clone, Debug, serde::Deserialize, Eq, PartialEq, serde::Serialize, TS)]
|
#[derive(Clone, serde::Deserialize, Eq, PartialEq)]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_config/settings/DatabaseConfig.ts"
|
|
||||||
)]
|
|
||||||
pub struct DatabaseConfig {
|
pub struct DatabaseConfig {
|
||||||
/// Enables database storage.
|
/// Enables database storage.
|
||||||
pub enabled: bool,
|
pub enabled: bool,
|
||||||
@@ -72,33 +44,26 @@ pub struct DatabaseConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// PostgreSQL backend configuration.
|
/// PostgreSQL backend configuration.
|
||||||
#[derive(Clone, Debug, serde::Deserialize, Eq, PartialEq, serde::Serialize, TS)]
|
#[derive(Clone, serde::Deserialize, Eq, PartialEq)]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_config/settings/PostgresConfig.ts"
|
|
||||||
)]
|
|
||||||
pub struct PostgresConfig {
|
pub struct PostgresConfig {
|
||||||
/// PostgreSQL URL or local placeholder.
|
/// PostgreSQL URL or local placeholder.
|
||||||
pub url: std::string::String,
|
pub url: std::string::String,
|
||||||
/// Maximum connection count.
|
/// Maximum connection count.
|
||||||
pub max_connections: u32,
|
pub max_connections: u32,
|
||||||
/// Connection timeout in milliseconds.
|
/// Connection timeout in milliseconds.
|
||||||
#[ts(type = "number")]
|
|
||||||
pub connect_timeout_ms: u64,
|
pub connect_timeout_ms: u64,
|
||||||
/// Enables schema initialization at startup.
|
/// Enables schema initialization at startup.
|
||||||
pub auto_initialize_schema: bool,
|
pub auto_initialize_schema: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// SQLite backend configuration.
|
/// SQLite backend configuration.
|
||||||
#[derive(Clone, Debug, serde::Deserialize, Eq, PartialEq, serde::Serialize, TS)]
|
#[derive(Clone, serde::Deserialize, Eq, PartialEq)]
|
||||||
#[ts(export, export_to = "../frontend/ts/bindings/ks_config/settings/SqliteConfig.ts")]
|
|
||||||
pub struct SqliteConfig {
|
pub struct SqliteConfig {
|
||||||
/// SQLite database path.
|
/// SQLite database path.
|
||||||
pub path: std::string::String,
|
pub path: std::string::String,
|
||||||
/// Creates the file when missing.
|
/// Creates the file when missing.
|
||||||
pub create_if_missing: bool,
|
pub create_if_missing: bool,
|
||||||
/// Busy timeout in milliseconds.
|
/// Busy timeout in milliseconds.
|
||||||
#[ts(type = "number")]
|
|
||||||
pub busy_timeout_ms: u64,
|
pub busy_timeout_ms: u64,
|
||||||
/// Maximum connection count.
|
/// Maximum connection count.
|
||||||
pub max_connections: u32,
|
pub max_connections: u32,
|
||||||
@@ -109,8 +74,7 @@ pub struct SqliteConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Solana endpoints and listener configuration.
|
/// Solana endpoints and listener configuration.
|
||||||
#[derive(Clone, Debug, serde::Deserialize, Eq, PartialEq, serde::Serialize, TS)]
|
#[derive(Clone, serde::Deserialize, Eq, PartialEq)]
|
||||||
#[ts(export, export_to = "../frontend/ts/bindings/ks_config/settings/SolanaConfig.ts")]
|
|
||||||
pub struct SolanaConfig {
|
pub struct SolanaConfig {
|
||||||
/// HTTP JSON-RPC endpoints.
|
/// HTTP JSON-RPC endpoints.
|
||||||
pub http_endpoints: std::vec::Vec<HttpEndpointConfig>,
|
pub http_endpoints: std::vec::Vec<HttpEndpointConfig>,
|
||||||
@@ -121,11 +85,7 @@ pub struct SolanaConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// HTTP JSON-RPC endpoint configuration.
|
/// HTTP JSON-RPC endpoint configuration.
|
||||||
#[derive(Clone, Debug, serde::Deserialize, Eq, PartialEq, serde::Serialize, TS)]
|
#[derive(Clone, serde::Deserialize, Eq, PartialEq)]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_config/settings/HttpEndpointConfig.ts"
|
|
||||||
)]
|
|
||||||
pub struct HttpEndpointConfig {
|
pub struct HttpEndpointConfig {
|
||||||
/// Endpoint name.
|
/// Endpoint name.
|
||||||
pub name: std::string::String,
|
pub name: std::string::String,
|
||||||
@@ -138,10 +98,8 @@ pub struct HttpEndpointConfig {
|
|||||||
/// Full endpoint URL.
|
/// Full endpoint URL.
|
||||||
pub url: std::string::String,
|
pub url: std::string::String,
|
||||||
/// Connection timeout in milliseconds.
|
/// Connection timeout in milliseconds.
|
||||||
#[ts(type = "number")]
|
|
||||||
pub connect_timeout_ms: u64,
|
pub connect_timeout_ms: u64,
|
||||||
/// Request timeout in milliseconds.
|
/// Request timeout in milliseconds.
|
||||||
#[ts(type = "number")]
|
|
||||||
pub request_timeout_ms: u64,
|
pub request_timeout_ms: u64,
|
||||||
/// Maximum idle connections per host.
|
/// Maximum idle connections per host.
|
||||||
pub max_idle_connections_per_host: u32,
|
pub max_idle_connections_per_host: u32,
|
||||||
@@ -150,11 +108,7 @@ pub struct HttpEndpointConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Standard Solana WebSocket endpoint configuration.
|
/// Standard Solana WebSocket endpoint configuration.
|
||||||
#[derive(Clone, Debug, serde::Deserialize, Eq, PartialEq, serde::Serialize, TS)]
|
#[derive(Clone, serde::Deserialize, Eq, PartialEq)]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_config/settings/WsEndpointConfig.ts"
|
|
||||||
)]
|
|
||||||
pub struct WsEndpointConfig {
|
pub struct WsEndpointConfig {
|
||||||
/// Endpoint name.
|
/// Endpoint name.
|
||||||
pub name: std::string::String,
|
pub name: std::string::String,
|
||||||
@@ -167,13 +121,10 @@ pub struct WsEndpointConfig {
|
|||||||
/// Full endpoint URL.
|
/// Full endpoint URL.
|
||||||
pub url: std::string::String,
|
pub url: std::string::String,
|
||||||
/// Connection timeout in milliseconds.
|
/// Connection timeout in milliseconds.
|
||||||
#[ts(type = "number")]
|
|
||||||
pub connect_timeout_ms: u64,
|
pub connect_timeout_ms: u64,
|
||||||
/// Request timeout in milliseconds.
|
/// Request timeout in milliseconds.
|
||||||
#[ts(type = "number")]
|
|
||||||
pub request_timeout_ms: u64,
|
pub request_timeout_ms: u64,
|
||||||
/// Unsubscribe timeout in milliseconds.
|
/// Unsubscribe timeout in milliseconds.
|
||||||
#[ts(type = "number")]
|
|
||||||
pub unsubscribe_timeout_ms: u64,
|
pub unsubscribe_timeout_ms: u64,
|
||||||
/// Writer channel capacity.
|
/// Writer channel capacity.
|
||||||
pub write_channel_capacity: u32,
|
pub write_channel_capacity: u32,
|
||||||
@@ -186,11 +137,7 @@ pub struct WsEndpointConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Role-specific endpoint limits.
|
/// Role-specific endpoint limits.
|
||||||
#[derive(Clone, Debug, serde::Deserialize, Eq, PartialEq, serde::Serialize, TS)]
|
#[derive(Clone, serde::Deserialize, Eq, PartialEq)]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_config/settings/EndpointRoleConfig.ts"
|
|
||||||
)]
|
|
||||||
pub struct EndpointRoleConfig {
|
pub struct EndpointRoleConfig {
|
||||||
/// Role code used by endpoint pools.
|
/// Role code used by endpoint pools.
|
||||||
pub role: std::string::String,
|
pub role: std::string::String,
|
||||||
@@ -209,16 +156,11 @@ pub struct EndpointRoleConfig {
|
|||||||
/// Maximum subscriptions allowed for this role on this URL.
|
/// Maximum subscriptions allowed for this role on this URL.
|
||||||
pub max_subscriptions: u32,
|
pub max_subscriptions: u32,
|
||||||
/// Pause after a rate limit response in milliseconds.
|
/// Pause after a rate limit response in milliseconds.
|
||||||
#[ts(type = "number")]
|
|
||||||
pub pause_after_rate_limit_ms: u64,
|
pub pause_after_rate_limit_ms: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Listener configuration used by standard WebSocket subscriptions.
|
/// Listener configuration used by standard WebSocket subscriptions.
|
||||||
#[derive(Clone, Debug, serde::Deserialize, Eq, PartialEq, serde::Serialize, TS)]
|
#[derive(Clone, serde::Deserialize, Eq, PartialEq)]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_config/settings/ListenerConfig.ts"
|
|
||||||
)]
|
|
||||||
pub struct ListenerConfig {
|
pub struct ListenerConfig {
|
||||||
/// Enables listener creation.
|
/// Enables listener creation.
|
||||||
pub enabled: bool,
|
pub enabled: bool,
|
||||||
@@ -233,11 +175,7 @@ pub struct ListenerConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Log listener filtered by a program identifier mention.
|
/// Log listener filtered by a program identifier mention.
|
||||||
#[derive(Clone, Debug, serde::Deserialize, Eq, PartialEq, serde::Serialize, TS)]
|
#[derive(Clone, serde::Deserialize, Eq, PartialEq)]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_config/settings/LogListenerConfig.ts"
|
|
||||||
)]
|
|
||||||
pub struct LogListenerConfig {
|
pub struct LogListenerConfig {
|
||||||
/// Listener name.
|
/// Listener name.
|
||||||
pub name: std::string::String,
|
pub name: std::string::String,
|
||||||
@@ -252,11 +190,7 @@ pub struct LogListenerConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Program account listener.
|
/// Program account listener.
|
||||||
#[derive(Clone, Debug, serde::Deserialize, Eq, PartialEq, serde::Serialize, TS)]
|
#[derive(Clone, serde::Deserialize, Eq, PartialEq)]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_config/settings/ProgramListenerConfig.ts"
|
|
||||||
)]
|
|
||||||
pub struct ProgramListenerConfig {
|
pub struct ProgramListenerConfig {
|
||||||
/// Listener name.
|
/// Listener name.
|
||||||
pub name: std::string::String,
|
pub name: std::string::String,
|
||||||
@@ -271,11 +205,7 @@ pub struct ProgramListenerConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Account listener.
|
/// Account listener.
|
||||||
#[derive(Clone, Debug, serde::Deserialize, Eq, PartialEq, serde::Serialize, TS)]
|
#[derive(Clone, serde::Deserialize, Eq, PartialEq)]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_config/settings/AccountListenerConfig.ts"
|
|
||||||
)]
|
|
||||||
pub struct AccountListenerConfig {
|
pub struct AccountListenerConfig {
|
||||||
/// Listener name.
|
/// Listener name.
|
||||||
pub name: std::string::String,
|
pub name: std::string::String,
|
||||||
@@ -290,8 +220,7 @@ pub struct AccountListenerConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Wallet configuration.
|
/// Wallet configuration.
|
||||||
#[derive(Clone, Debug, serde::Deserialize, Eq, PartialEq, serde::Serialize, TS)]
|
#[derive(Clone, serde::Deserialize, Eq, PartialEq)]
|
||||||
#[ts(export, export_to = "../frontend/ts/bindings/ks_config/settings/WalletConfig.ts")]
|
|
||||||
pub struct WalletConfig {
|
pub struct WalletConfig {
|
||||||
/// Wallet directory path.
|
/// Wallet directory path.
|
||||||
pub wallet_dir: std::string::String,
|
pub wallet_dir: std::string::String,
|
||||||
@@ -306,11 +235,7 @@ pub struct WalletConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Execution safety configuration.
|
/// Execution safety configuration.
|
||||||
#[derive(Clone, Debug, serde::Deserialize, Eq, PartialEq, serde::Serialize, TS)]
|
#[derive(Clone, serde::Deserialize, Eq, PartialEq)]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_config/settings/ExecutionConfig.ts"
|
|
||||||
)]
|
|
||||||
pub struct ExecutionConfig {
|
pub struct ExecutionConfig {
|
||||||
/// Enables local validator transaction sending.
|
/// Enables local validator transaction sending.
|
||||||
pub localnet_send_enabled: bool,
|
pub localnet_send_enabled: bool,
|
||||||
@@ -327,48 +252,29 @@ pub struct ExecutionConfig {
|
|||||||
/// Requires explicit operator confirmation before send.
|
/// Requires explicit operator confirmation before send.
|
||||||
pub require_operator_confirmation: bool,
|
pub require_operator_confirmation: bool,
|
||||||
/// Maximum spend in lamports for local validator tests.
|
/// Maximum spend in lamports for local validator tests.
|
||||||
#[ts(type = "number")]
|
|
||||||
pub localnet_max_spend_lamports: u64,
|
pub localnet_max_spend_lamports: u64,
|
||||||
/// Maximum spend in lamports for devnet tests.
|
/// Maximum spend in lamports for devnet tests.
|
||||||
#[ts(type = "number")]
|
|
||||||
pub devnet_max_spend_lamports: u64,
|
pub devnet_max_spend_lamports: u64,
|
||||||
/// Maximum spend in lamports for testnet tests.
|
/// Maximum spend in lamports for testnet tests.
|
||||||
#[ts(type = "number")]
|
|
||||||
pub testnet_max_spend_lamports: u64,
|
pub testnet_max_spend_lamports: u64,
|
||||||
/// Maximum spend in lamports for mainnet operations.
|
/// Maximum spend in lamports for mainnet operations.
|
||||||
#[ts(type = "number")]
|
|
||||||
pub mainnet_max_spend_lamports: u64,
|
pub mainnet_max_spend_lamports: u64,
|
||||||
/// Maximum estimated transaction fee in lamports.
|
/// Maximum estimated transaction fee in lamports.
|
||||||
#[ts(type = "number")]
|
|
||||||
pub max_fee_lamports: u64,
|
pub max_fee_lamports: u64,
|
||||||
/// Maximum compute-unit price in micro-lamports.
|
/// Maximum compute-unit price in micro-lamports.
|
||||||
#[ts(type = "number")]
|
|
||||||
pub max_compute_unit_price_micro_lamports: u64,
|
pub max_compute_unit_price_micro_lamports: u64,
|
||||||
/// Maximum accepted age for a recent blockhash in slots.
|
/// Maximum accepted age for a recent blockhash in slots.
|
||||||
#[ts(type = "number")]
|
|
||||||
pub recent_blockhash_max_age_slots: u64,
|
pub recent_blockhash_max_age_slots: u64,
|
||||||
/// Maximum node retransmission retries requested by `sendTransaction`.
|
/// Maximum node retransmission retries requested by `sendTransaction`.
|
||||||
pub send_max_retries: u32,
|
pub send_max_retries: u32,
|
||||||
/// Delay between transaction confirmation polls.
|
/// Delay between transaction confirmation polls.
|
||||||
#[ts(type = "number")]
|
|
||||||
pub confirmation_poll_interval_ms: u64,
|
pub confirmation_poll_interval_ms: u64,
|
||||||
/// Maximum number of transaction confirmation polls.
|
/// Maximum number of transaction confirmation polls.
|
||||||
pub confirmation_max_attempts: u32,
|
pub confirmation_max_attempts: u32,
|
||||||
/// Maximum devnet faucet airdrop allowed for a temporary wallet.
|
/// Maximum devnet faucet airdrop allowed for a temporary wallet.
|
||||||
#[ts(type = "number")]
|
|
||||||
pub devnet_airdrop_max_lamports: u64,
|
pub devnet_airdrop_max_lamports: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Demo application configuration.
|
|
||||||
#[derive(Clone, Debug, serde::Deserialize, Eq, PartialEq, serde::Serialize, TS)]
|
|
||||||
#[ts(export, export_to = "../frontend/ts/bindings/ks_config/settings/DemoConfig.ts")]
|
|
||||||
pub struct DemoConfig {
|
|
||||||
/// Enables live demo pages.
|
|
||||||
pub live_demo_enabled: bool,
|
|
||||||
/// Enables trading demo pages.
|
|
||||||
pub trading_demo_enabled: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the embedded JSON Schema text used for resolved runtime contract validation.
|
/// Returns the embedded JSON Schema text used for resolved runtime contract validation.
|
||||||
pub fn config_json_schema_text() -> &'static str {
|
pub fn config_json_schema_text() -> &'static str {
|
||||||
return CONFIG_JSON_SCHEMA;
|
return CONFIG_JSON_SCHEMA;
|
||||||
@@ -413,9 +319,9 @@ pub fn validate_config_json_schema(raw_json: &str) -> ks_core::Result<()> {
|
|||||||
let validation_result = validator.validate(&instance);
|
let validation_result = validator.validate(&instance);
|
||||||
return match validation_result {
|
return match validation_result {
|
||||||
std::result::Result::Ok(()) => std::result::Result::Ok(()),
|
std::result::Result::Ok(()) => std::result::Result::Ok(()),
|
||||||
std::result::Result::Err(error) => std::result::Result::Err(ks_core::Error::new(
|
std::result::Result::Err(_) => std::result::Result::Err(ks_core::Error::new(
|
||||||
"config_json_schema_validation_failed",
|
"config_json_schema_validation_failed",
|
||||||
error.to_string(),
|
"resolved configuration does not satisfy its schema",
|
||||||
)),
|
)),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -428,10 +334,10 @@ pub fn parse_config_json(raw_json: &str) -> ks_core::Result<AppConfig> {
|
|||||||
}
|
}
|
||||||
let config = match serde_json::from_str::<AppConfig>(raw_json) {
|
let config = match serde_json::from_str::<AppConfig>(raw_json) {
|
||||||
std::result::Result::Ok(config) => config,
|
std::result::Result::Ok(config) => config,
|
||||||
std::result::Result::Err(error) => {
|
std::result::Result::Err(_) => {
|
||||||
return std::result::Result::Err(ks_core::Error::new(
|
return std::result::Result::Err(ks_core::Error::new(
|
||||||
"config_json_decode_failed",
|
"config_json_decode_failed",
|
||||||
error.to_string(),
|
"resolved configuration could not be decoded",
|
||||||
));
|
));
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -477,36 +383,6 @@ pub fn read_config_json_file_with_environment(
|
|||||||
return parse_config_json(&resolved);
|
return parse_config_json(&resolved);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Serializes a configuration value to compact JSON.
|
|
||||||
pub fn serialize_config_json(config: &AppConfig) -> ks_core::Result<std::string::String> {
|
|
||||||
match validate_config(config) {
|
|
||||||
std::result::Result::Ok(()) => (),
|
|
||||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
|
||||||
}
|
|
||||||
return match serde_json::to_string(config) {
|
|
||||||
std::result::Result::Ok(serialized) => std::result::Result::Ok(serialized),
|
|
||||||
std::result::Result::Err(error) => std::result::Result::Err(ks_core::Error::new(
|
|
||||||
"config_json_serialize_failed",
|
|
||||||
error.to_string(),
|
|
||||||
)),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Serializes a configuration value to pretty JSON.
|
|
||||||
pub fn serialize_config_json_pretty(config: &AppConfig) -> ks_core::Result<std::string::String> {
|
|
||||||
match validate_config(config) {
|
|
||||||
std::result::Result::Ok(()) => (),
|
|
||||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
|
||||||
}
|
|
||||||
return match serde_json::to_string_pretty(config) {
|
|
||||||
std::result::Result::Ok(serialized) => std::result::Result::Ok(serialized),
|
|
||||||
std::result::Result::Err(error) => std::result::Result::Err(ks_core::Error::new(
|
|
||||||
"config_json_pretty_serialize_failed",
|
|
||||||
error.to_string(),
|
|
||||||
)),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the active profile declared by the root configuration.
|
/// Returns the active profile declared by the root configuration.
|
||||||
pub fn active_profile(config: &AppConfig) -> ks_core::Result<&ProfileConfig> {
|
pub fn active_profile(config: &AppConfig) -> ks_core::Result<&ProfileConfig> {
|
||||||
for profile in &config.profiles {
|
for profile in &config.profiles {
|
||||||
@@ -576,10 +452,6 @@ fn validate_root_config(config: &AppConfig) -> ks_core::Result<()> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn validate_profile(profile: &ProfileConfig) -> ks_core::Result<()> {
|
fn validate_profile(profile: &ProfileConfig) -> ks_core::Result<()> {
|
||||||
match validate_app_section(&profile.app) {
|
|
||||||
std::result::Result::Ok(()) => (),
|
|
||||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
|
||||||
}
|
|
||||||
match validate_database(&profile.database) {
|
match validate_database(&profile.database) {
|
||||||
std::result::Result::Ok(()) => (),
|
std::result::Result::Ok(()) => (),
|
||||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||||
@@ -599,14 +471,6 @@ fn validate_profile(profile: &ProfileConfig) -> ks_core::Result<()> {
|
|||||||
return validate_wallet_execution_pair(&profile.wallet, &profile.execution);
|
return validate_wallet_execution_pair(&profile.wallet, &profile.execution);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn validate_app_section(config: &AppSectionConfig) -> ks_core::Result<()> {
|
|
||||||
match require_non_empty(&config.name, "app.name") {
|
|
||||||
std::result::Result::Ok(()) => (),
|
|
||||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
|
||||||
}
|
|
||||||
return require_non_empty(&config.environment, "app.environment");
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn validate_database(config: &DatabaseConfig) -> ks_core::Result<()> {
|
pub(crate) fn validate_database(config: &DatabaseConfig) -> ks_core::Result<()> {
|
||||||
if config.backend != "postgres" && config.backend != "sqlite" {
|
if config.backend != "postgres" && config.backend != "sqlite" {
|
||||||
return std::result::Result::Err(ks_core::Error::new(
|
return std::result::Result::Err(ks_core::Error::new(
|
||||||
@@ -683,7 +547,7 @@ pub(crate) fn validate_http_endpoint(config: &HttpEndpointConfig) -> ks_core::Re
|
|||||||
if !config.url.starts_with("http://") && !config.url.starts_with("https://") {
|
if !config.url.starts_with("http://") && !config.url.starts_with("https://") {
|
||||||
return std::result::Result::Err(ks_core::Error::new(
|
return std::result::Result::Err(ks_core::Error::new(
|
||||||
"http_endpoint_url_invalid",
|
"http_endpoint_url_invalid",
|
||||||
config.url.clone(),
|
config.name.clone(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
if config.connect_timeout_ms == 0
|
if config.connect_timeout_ms == 0
|
||||||
@@ -714,7 +578,7 @@ pub(crate) fn validate_ws_endpoint(config: &WsEndpointConfig) -> ks_core::Result
|
|||||||
if !config.url.starts_with("ws://") && !config.url.starts_with("wss://") {
|
if !config.url.starts_with("ws://") && !config.url.starts_with("wss://") {
|
||||||
return std::result::Result::Err(ks_core::Error::new(
|
return std::result::Result::Err(ks_core::Error::new(
|
||||||
"ws_endpoint_url_invalid",
|
"ws_endpoint_url_invalid",
|
||||||
config.url.clone(),
|
config.name.clone(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
if config.connect_timeout_ms == 0
|
if config.connect_timeout_ms == 0
|
||||||
@@ -1006,24 +870,6 @@ pub(crate) fn require_non_empty(value: &str, field_name: &str) -> ks_core::Resul
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use ts_rs::TS; // rust-rules: derive-import
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn exported_json_configuration_numbers_do_not_use_bigint() {
|
|
||||||
let config = ts_rs::Config::default();
|
|
||||||
let declarations = [
|
|
||||||
<crate::PostgresConfig as TS>::decl(&config),
|
|
||||||
<crate::SqliteConfig as TS>::decl(&config),
|
|
||||||
<crate::HttpEndpointConfig as TS>::decl(&config),
|
|
||||||
<crate::WsEndpointConfig as TS>::decl(&config),
|
|
||||||
<crate::EndpointRoleConfig as TS>::decl(&config),
|
|
||||||
<crate::ExecutionConfig as TS>::decl(&config),
|
|
||||||
];
|
|
||||||
for declaration in declarations {
|
|
||||||
assert!(!declaration.contains("bigint"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const DEFAULT_CONFIG: &str =
|
const DEFAULT_CONFIG: &str =
|
||||||
include_str!("../../test-fixtures/config/resolved.app.config.json");
|
include_str!("../../test-fixtures/config/resolved.app.config.json");
|
||||||
const EXAMPLE_CONFIG: &str =
|
const EXAMPLE_CONFIG: &str =
|
||||||
@@ -1077,29 +923,6 @@ mod tests {
|
|||||||
//assert_eq!(active.name, "local_devnet");
|
//assert_eq!(active.name, "local_devnet");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn default_app_config_serializes_and_roundtrips() {
|
|
||||||
let config_result = super::parse_config_json(DEFAULT_CONFIG);
|
|
||||||
assert!(config_result.is_ok());
|
|
||||||
let config = match config_result {
|
|
||||||
std::result::Result::Ok(config) => config,
|
|
||||||
std::result::Result::Err(error) => panic!("default app config must parse: {error}"),
|
|
||||||
};
|
|
||||||
let serialized_result = super::serialize_config_json_pretty(&config);
|
|
||||||
assert!(serialized_result.is_ok());
|
|
||||||
let serialized = match serialized_result {
|
|
||||||
std::result::Result::Ok(serialized) => serialized,
|
|
||||||
std::result::Result::Err(error) => panic!("default app config must serialize: {error}"),
|
|
||||||
};
|
|
||||||
let reparsed_result = super::parse_config_json(&serialized);
|
|
||||||
assert!(reparsed_result.is_ok());
|
|
||||||
let reparsed = match reparsed_result {
|
|
||||||
std::result::Result::Ok(reparsed) => reparsed,
|
|
||||||
std::result::Result::Err(error) => panic!("serialized config must parse: {error}"),
|
|
||||||
};
|
|
||||||
assert_eq!(config, reparsed);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parser_rejects_missing_active_profile() {
|
fn parser_rejects_missing_active_profile() {
|
||||||
let mut value = parse_default_value();
|
let mut value = parse_default_value();
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
// file: ks-config/src/store.rs
|
// file: ks-config/src/store.rs
|
||||||
// version: 1
|
// version: 2
|
||||||
|
|
||||||
//! Independent store configuration document loading and validation.
|
//! Independent store configuration document loading and validation.
|
||||||
|
|
||||||
const STORE_JSON_SCHEMA: &str = include_str!("../../config/schemas/store.config.schema.json");
|
const STORE_JSON_SCHEMA: &str = include_str!("../../config/schemas/store.config.schema.json");
|
||||||
|
|
||||||
/// Root store document with one default profile and named alternatives.
|
/// Root store document with one default profile and named alternatives.
|
||||||
#[derive(Clone, Debug, serde::Deserialize, Eq, PartialEq, serde::Serialize)]
|
#[derive(Clone, serde::Deserialize, Eq, PartialEq)]
|
||||||
pub struct StoreConfigDocument {
|
pub struct StoreConfigDocument {
|
||||||
/// Default store profile used when a composition does not override it.
|
/// Default store profile used when a composition does not override it.
|
||||||
pub default_profile: std::string::String,
|
pub default_profile: std::string::String,
|
||||||
@@ -15,7 +15,7 @@ pub struct StoreConfigDocument {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Named store profile.
|
/// Named store profile.
|
||||||
#[derive(Clone, Debug, serde::Deserialize, Eq, PartialEq, serde::Serialize)]
|
#[derive(Clone, serde::Deserialize, Eq, PartialEq)]
|
||||||
pub struct StoreProfileConfig {
|
pub struct StoreProfileConfig {
|
||||||
/// Profile code.
|
/// Profile code.
|
||||||
pub name: std::string::String,
|
pub name: std::string::String,
|
||||||
@@ -66,9 +66,9 @@ pub fn validate_store_json_schema(raw_json: &str) -> ks_core::Result<()> {
|
|||||||
};
|
};
|
||||||
return match validator.validate(&instance) {
|
return match validator.validate(&instance) {
|
||||||
std::result::Result::Ok(()) => std::result::Result::Ok(()),
|
std::result::Result::Ok(()) => std::result::Result::Ok(()),
|
||||||
std::result::Result::Err(error) => std::result::Result::Err(ks_core::Error::new(
|
std::result::Result::Err(_) => std::result::Result::Err(ks_core::Error::new(
|
||||||
"store_config_schema_validation_failed",
|
"store_config_schema_validation_failed",
|
||||||
error.to_string(),
|
"store configuration does not satisfy its schema",
|
||||||
)),
|
)),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -81,10 +81,10 @@ pub fn parse_store_json(raw_json: &str) -> ks_core::Result<StoreConfigDocument>
|
|||||||
}
|
}
|
||||||
let document = match serde_json::from_str::<StoreConfigDocument>(raw_json) {
|
let document = match serde_json::from_str::<StoreConfigDocument>(raw_json) {
|
||||||
std::result::Result::Ok(value) => value,
|
std::result::Result::Ok(value) => value,
|
||||||
std::result::Result::Err(error) => {
|
std::result::Result::Err(_) => {
|
||||||
return std::result::Result::Err(ks_core::Error::new(
|
return std::result::Result::Err(ks_core::Error::new(
|
||||||
"store_config_json_decode_failed",
|
"store_config_json_decode_failed",
|
||||||
error.to_string(),
|
"store configuration could not be decoded",
|
||||||
));
|
));
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -176,7 +176,7 @@ pub fn validate_store_document(document: &StoreConfigDocument) -> ks_core::Resul
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
const DEFAULT_STORE: &str = include_str!("../../config/store.config.json");
|
const DEFAULT_STORE: &str = include_str!("../../config/store.config.json");
|
||||||
const EXAMPLE_STORE: &str = include_str!("../../config/example.store.config.json");
|
const EXAMPLE_STORE: &str = include_str!("../../config/exemples/example.store.config.json");
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn default_and_example_store_configs_validate() {
|
fn default_and_example_store_configs_validate() {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// file: ks-config/src/transport.rs
|
// file: ks-config/src/transport.rs
|
||||||
// version: 2
|
// version: 3
|
||||||
|
|
||||||
//! Independent Solana transport configuration document loading and validation.
|
//! Independent Solana transport configuration document loading and validation.
|
||||||
|
|
||||||
@@ -7,7 +7,7 @@ const TRANSPORT_JSON_SCHEMA: &str =
|
|||||||
include_str!("../../config/schemas/transport.config.schema.json");
|
include_str!("../../config/schemas/transport.config.schema.json");
|
||||||
|
|
||||||
/// Root transport document containing shared endpoint defaults and named profiles.
|
/// Root transport document containing shared endpoint defaults and named profiles.
|
||||||
#[derive(Clone, Debug, serde::Deserialize, Eq, PartialEq, serde::Serialize)]
|
#[derive(Clone, serde::Deserialize, Eq, PartialEq)]
|
||||||
pub struct TransportConfigDocument {
|
pub struct TransportConfigDocument {
|
||||||
/// Default transport profile used when a composition does not override it.
|
/// Default transport profile used when a composition does not override it.
|
||||||
pub default_profile: std::string::String,
|
pub default_profile: std::string::String,
|
||||||
@@ -18,7 +18,7 @@ pub struct TransportConfigDocument {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Default values shared by one class of WebSocket endpoints.
|
/// Default values shared by one class of WebSocket endpoints.
|
||||||
#[derive(Clone, Debug, serde::Deserialize, Eq, PartialEq, serde::Serialize)]
|
#[derive(Clone, serde::Deserialize, Eq, PartialEq)]
|
||||||
pub struct WsEndpointDefaultsConfig {
|
pub struct WsEndpointDefaultsConfig {
|
||||||
/// Defaults code referenced by endpoints.
|
/// Defaults code referenced by endpoints.
|
||||||
pub name: std::string::String,
|
pub name: std::string::String,
|
||||||
@@ -37,7 +37,7 @@ pub struct WsEndpointDefaultsConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Endpoint-specific overrides applied on top of named WebSocket defaults.
|
/// Endpoint-specific overrides applied on top of named WebSocket defaults.
|
||||||
#[derive(Clone, Debug, Default, serde::Deserialize, Eq, PartialEq, serde::Serialize)]
|
#[derive(Clone, Default, serde::Deserialize, Eq, PartialEq)]
|
||||||
pub struct WsEndpointOverridesConfig {
|
pub struct WsEndpointOverridesConfig {
|
||||||
/// Optional connection timeout override.
|
/// Optional connection timeout override.
|
||||||
pub connect_timeout_ms: std::option::Option<u64>,
|
pub connect_timeout_ms: std::option::Option<u64>,
|
||||||
@@ -54,7 +54,7 @@ pub struct WsEndpointOverridesConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Source shape of one WebSocket endpoint before defaults are resolved.
|
/// Source shape of one WebSocket endpoint before defaults are resolved.
|
||||||
#[derive(Clone, Debug, serde::Deserialize, Eq, PartialEq, serde::Serialize)]
|
#[derive(Clone, serde::Deserialize, Eq, PartialEq)]
|
||||||
pub struct WsEndpointSourceConfig {
|
pub struct WsEndpointSourceConfig {
|
||||||
/// Endpoint name.
|
/// Endpoint name.
|
||||||
pub name: std::string::String,
|
pub name: std::string::String,
|
||||||
@@ -76,7 +76,7 @@ pub struct WsEndpointSourceConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Named Solana HTTP and WebSocket endpoint source profile.
|
/// Named Solana HTTP and WebSocket endpoint source profile.
|
||||||
#[derive(Clone, Debug, serde::Deserialize, Eq, PartialEq, serde::Serialize)]
|
#[derive(Clone, serde::Deserialize, Eq, PartialEq)]
|
||||||
pub struct TransportProfileSourceConfig {
|
pub struct TransportProfileSourceConfig {
|
||||||
/// Profile code.
|
/// Profile code.
|
||||||
pub name: std::string::String,
|
pub name: std::string::String,
|
||||||
@@ -87,7 +87,7 @@ pub struct TransportProfileSourceConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Fully resolved transport profile consumed by transport clients.
|
/// Fully resolved transport profile consumed by transport clients.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Eq, PartialEq)]
|
||||||
pub struct TransportProfileConfig {
|
pub struct TransportProfileConfig {
|
||||||
/// Profile code.
|
/// Profile code.
|
||||||
pub name: std::string::String,
|
pub name: std::string::String,
|
||||||
@@ -140,9 +140,9 @@ pub fn validate_transport_json_schema(raw_json: &str) -> ks_core::Result<()> {
|
|||||||
};
|
};
|
||||||
return match validator.validate(&instance) {
|
return match validator.validate(&instance) {
|
||||||
std::result::Result::Ok(()) => std::result::Result::Ok(()),
|
std::result::Result::Ok(()) => std::result::Result::Ok(()),
|
||||||
std::result::Result::Err(error) => std::result::Result::Err(ks_core::Error::new(
|
std::result::Result::Err(_) => std::result::Result::Err(ks_core::Error::new(
|
||||||
"transport_config_schema_validation_failed",
|
"transport_config_schema_validation_failed",
|
||||||
error.to_string(),
|
"transport configuration does not satisfy its schema",
|
||||||
)),
|
)),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -155,10 +155,10 @@ pub fn parse_transport_json(raw_json: &str) -> ks_core::Result<TransportConfigDo
|
|||||||
}
|
}
|
||||||
let document = match serde_json::from_str::<TransportConfigDocument>(raw_json) {
|
let document = match serde_json::from_str::<TransportConfigDocument>(raw_json) {
|
||||||
std::result::Result::Ok(value) => value,
|
std::result::Result::Ok(value) => value,
|
||||||
std::result::Result::Err(error) => {
|
std::result::Result::Err(_) => {
|
||||||
return std::result::Result::Err(ks_core::Error::new(
|
return std::result::Result::Err(ks_core::Error::new(
|
||||||
"transport_config_json_decode_failed",
|
"transport_config_json_decode_failed",
|
||||||
error.to_string(),
|
"transport configuration could not be decoded",
|
||||||
));
|
));
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -393,7 +393,8 @@ pub fn validate_transport_document(document: &TransportConfigDocument) -> ks_cor
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
const DEFAULT_TRANSPORT: &str = include_str!("../../config/transport.config.json");
|
const DEFAULT_TRANSPORT: &str = include_str!("../../config/transport.config.json");
|
||||||
const EXAMPLE_TRANSPORT: &str = include_str!("../../config/example.transport.config.json");
|
const EXAMPLE_TRANSPORT: &str =
|
||||||
|
include_str!("../../config/exemples/example.transport.config.json");
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn default_and_example_transport_configs_validate() {
|
fn default_and_example_transport_configs_validate() {
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
// file: ks-config/src/wallet.rs
|
// file: ks-config/src/wallet.rs
|
||||||
// version: 1
|
// version: 3
|
||||||
|
|
||||||
//! Independent wallet configuration document loading and validation.
|
//! Independent wallet configuration document loading and validation.
|
||||||
|
|
||||||
const WALLET_JSON_SCHEMA: &str = include_str!("../../config/schemas/wallet.config.schema.json");
|
const WALLET_JSON_SCHEMA: &str = include_str!("../../config/schemas/wallet.config.schema.json");
|
||||||
|
|
||||||
/// Root wallet document with global storage and named runtime profiles.
|
/// Root wallet document with global storage and named runtime profiles.
|
||||||
#[derive(Clone, Debug, serde::Deserialize, Eq, PartialEq, serde::Serialize)]
|
#[derive(Clone, serde::Deserialize, Eq, PartialEq)]
|
||||||
pub struct WalletConfigDocument {
|
pub struct WalletConfigDocument {
|
||||||
/// Root directory for wallet storage, independent from profile selection.
|
/// Root directory for wallet storage, independent from profile selection.
|
||||||
pub wallets_directory: std::string::String,
|
pub wallets_directory: std::string::String,
|
||||||
@@ -17,7 +17,7 @@ pub struct WalletConfigDocument {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Named wallet profile whose directory is relative to the global wallet root unless absolute.
|
/// Named wallet profile whose directory is relative to the global wallet root unless absolute.
|
||||||
#[derive(Clone, Debug, serde::Deserialize, Eq, PartialEq, serde::Serialize)]
|
#[derive(Clone, serde::Deserialize, Eq, PartialEq)]
|
||||||
pub struct WalletProfileConfig {
|
pub struct WalletProfileConfig {
|
||||||
/// Profile code.
|
/// Profile code.
|
||||||
pub name: std::string::String,
|
pub name: std::string::String,
|
||||||
@@ -67,18 +67,18 @@ pub fn parse_wallet_json(raw_json: &str) -> ks_core::Result<WalletConfigDocument
|
|||||||
));
|
));
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
if let std::result::Result::Err(error) = validator.validate(&instance) {
|
if validator.validate(&instance).is_err() {
|
||||||
return std::result::Result::Err(ks_core::Error::new(
|
return std::result::Result::Err(ks_core::Error::new(
|
||||||
"wallet_config_schema_validation_failed",
|
"wallet_config_schema_validation_failed",
|
||||||
error.to_string(),
|
"wallet configuration does not satisfy its schema",
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
let document = match serde_json::from_str::<WalletConfigDocument>(raw_json) {
|
let document = match serde_json::from_str::<WalletConfigDocument>(raw_json) {
|
||||||
std::result::Result::Ok(value) => value,
|
std::result::Result::Ok(value) => value,
|
||||||
std::result::Result::Err(error) => {
|
std::result::Result::Err(_) => {
|
||||||
return std::result::Result::Err(ks_core::Error::new(
|
return std::result::Result::Err(ks_core::Error::new(
|
||||||
"wallet_config_json_decode_failed",
|
"wallet_config_json_decode_failed",
|
||||||
error.to_string(),
|
"wallet configuration could not be decoded",
|
||||||
));
|
));
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -206,7 +206,7 @@ pub fn validate_wallet_document(document: &WalletConfigDocument) -> ks_core::Res
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
const DEFAULT_WALLET: &str = include_str!("../../config/wallet.config.json");
|
const DEFAULT_WALLET: &str = include_str!("../../config/wallet.config.json");
|
||||||
const EXAMPLE_WALLET: &str = include_str!("../../config/example.wallet.config.json");
|
const EXAMPLE_WALLET: &str = include_str!("../../config/exemples/example.wallet.config.json");
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn default_and_example_wallet_configs_validate() {
|
fn default_and_example_wallet_configs_validate() {
|
||||||
|
|||||||
@@ -6,36 +6,37 @@
|
|||||||
#[test]
|
#[test]
|
||||||
fn external_consumer_resolves_composition_through_crate_root_exports() {
|
fn external_consumer_resolves_composition_through_crate_root_exports() {
|
||||||
let composition = match ks_config::parse_composition_json(include_str!(
|
let composition = match ks_config::parse_composition_json(include_str!(
|
||||||
"../../config/example.kb-app-demo-desktop.default.config.json"
|
"../../config/exemples/example.kb-app-demo-desktop.default.config.json"
|
||||||
)) {
|
)) {
|
||||||
std::result::Result::Ok(value) => value,
|
std::result::Result::Ok(value) => value,
|
||||||
std::result::Result::Err(error) => panic!("composition must parse: {error}"),
|
std::result::Result::Err(error) => panic!("composition must parse: {error}"),
|
||||||
};
|
};
|
||||||
let transport = match ks_config::parse_transport_json(include_str!(
|
let transport = match ks_config::parse_transport_json(include_str!(
|
||||||
"../../config/example.transport.config.json"
|
"../../config/exemples/example.transport.config.json"
|
||||||
)) {
|
)) {
|
||||||
std::result::Result::Ok(value) => value,
|
std::result::Result::Ok(value) => value,
|
||||||
std::result::Result::Err(error) => panic!("transport must parse: {error}"),
|
std::result::Result::Err(error) => panic!("transport must parse: {error}"),
|
||||||
};
|
};
|
||||||
let listeners = match ks_config::parse_listeners_json(include_str!(
|
let listeners = match ks_config::parse_listeners_json(include_str!(
|
||||||
"../../config/example.listeners.config.json"
|
"../../config/exemples/example.listeners.config.json"
|
||||||
)) {
|
)) {
|
||||||
std::result::Result::Ok(value) => value,
|
std::result::Result::Ok(value) => value,
|
||||||
std::result::Result::Err(error) => panic!("listeners must parse: {error}"),
|
std::result::Result::Err(error) => panic!("listeners must parse: {error}"),
|
||||||
};
|
};
|
||||||
let store =
|
let store = match ks_config::parse_store_json(include_str!(
|
||||||
match ks_config::parse_store_json(include_str!("../../config/example.store.config.json")) {
|
"../../config/exemples/example.store.config.json"
|
||||||
std::result::Result::Ok(value) => value,
|
)) {
|
||||||
std::result::Result::Err(error) => panic!("store must parse: {error}"),
|
std::result::Result::Ok(value) => value,
|
||||||
};
|
std::result::Result::Err(error) => panic!("store must parse: {error}"),
|
||||||
let wallet =
|
};
|
||||||
match ks_config::parse_wallet_json(include_str!("../../config/example.wallet.config.json"))
|
let wallet = match ks_config::parse_wallet_json(include_str!(
|
||||||
{
|
"../../config/exemples/example.wallet.config.json"
|
||||||
std::result::Result::Ok(value) => value,
|
)) {
|
||||||
std::result::Result::Err(error) => panic!("wallet must parse: {error}"),
|
std::result::Result::Ok(value) => value,
|
||||||
};
|
std::result::Result::Err(error) => panic!("wallet must parse: {error}"),
|
||||||
|
};
|
||||||
let execution = match ks_config::parse_execution_json(include_str!(
|
let execution = match ks_config::parse_execution_json(include_str!(
|
||||||
"../../config/example.execution.config.json"
|
"../../config/exemples/example.execution.config.json"
|
||||||
)) {
|
)) {
|
||||||
std::result::Result::Ok(value) => value,
|
std::result::Result::Ok(value) => value,
|
||||||
std::result::Result::Err(error) => panic!("execution must parse: {error}"),
|
std::result::Result::Err(error) => panic!("execution must parse: {error}"),
|
||||||
|
|||||||
18
ks-config/tests/external_sensitivity_api.rs
Normal file
18
ks-config/tests/external_sensitivity_api.rs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
// file: ks-config/tests/external_sensitivity_api.rs
|
||||||
|
// version: 1
|
||||||
|
|
||||||
|
//! External-contract coverage for configuration sensitivity helpers.
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn external_consumer_classifies_composed_values_and_redacts_secrets() {
|
||||||
|
let sensitivity = ks_config::classify_environment_template(
|
||||||
|
"https://provider.invalid/?api-key=${KS_SECRET_HELIUS_API_KEY}",
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
sensitivity,
|
||||||
|
std::option::Option::Some(ks_config::EnvironmentValueSensitivity::Secret)
|
||||||
|
);
|
||||||
|
let diagnostic =
|
||||||
|
ks_config::diagnostic_environment_value("KS_SECRET_HELIUS_API_KEY", "SECRET-CANARY");
|
||||||
|
assert_eq!(diagnostic, std::option::Option::Some("<redacted>".to_string()));
|
||||||
|
}
|
||||||
@@ -1,8 +1,13 @@
|
|||||||
<!-- file: ks-lib/CHANGELOG.md -->
|
<!-- file: ks-lib/CHANGELOG.md -->
|
||||||
<!-- version: 52 -->
|
<!-- version: 53 -->
|
||||||
|
|
||||||
# CHANGELOG — ks-lib
|
# CHANGELOG — ks-lib
|
||||||
|
|
||||||
|
## `0.5.1-pre.008`
|
||||||
|
|
||||||
|
- retire la dépendance `ts-rs`, les dérivations/attributs TS-RS et les bindings TypeScript générés historiques de `ks-lib` ;
|
||||||
|
- conserve inchangés les contrats Rust de décodage, matérialisation, exécution et modèles : toute exposition TypeScript appartient désormais à un DTO/wrapper de l'application consommatrice.
|
||||||
|
|
||||||
## `0.5.1-pre.003`
|
## `0.5.1-pre.003`
|
||||||
|
|
||||||
- migre les 255 identités runtime/persistables effectivement présentes de `kb-lib.decoder.*`, `kb-lib.executor.*` et `kb-lib.materializer.*` vers `ks-lib-decoder.*`, `ks-lib-executor.*` et `ks-lib-materializer.*` ;
|
- migre les 255 identités runtime/persistables effectivement présentes de `kb-lib.decoder.*`, `kb-lib.executor.*` et `kb-lib.materializer.*` vers `ks-lib-decoder.*`, `ks-lib-executor.*` et `ks-lib-materializer.*` ;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# file: ks-lib/Cargo.toml
|
# file: ks-lib/Cargo.toml
|
||||||
# version: 16
|
# version: 17
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "ks-lib"
|
name = "ks-lib"
|
||||||
@@ -47,7 +47,6 @@ spl-token-confidential-transfer-proof-extraction.workspace = true
|
|||||||
spl-token-interface.workspace = true
|
spl-token-interface.workspace = true
|
||||||
spl-memo-interface.workspace = true
|
spl-memo-interface.workspace = true
|
||||||
tracing.workspace = true
|
tracing.workspace = true
|
||||||
ts-rs.workspace = true
|
|
||||||
wincode.workspace = true
|
wincode.workspace = true
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<!-- file: ks-lib/README.md -->
|
<!-- file: ks-lib/README.md -->
|
||||||
<!-- version: 30 -->
|
<!-- version: 31 -->
|
||||||
|
|
||||||
# ks-lib
|
# ks-lib
|
||||||
|
|
||||||
@@ -65,6 +65,8 @@ L’inventaire audité comprend 25 composants nommés : onze matérialisateurs a
|
|||||||
|
|
||||||
`ks-lib` ne sélectionne aucun endpoint, ne lit pas directement un RPC, ne persiste aucune donnée, ne gère pas les secrets de wallet et ne soumet aucune transaction.
|
`ks-lib` ne sélectionne aucun endpoint, ne lit pas directement un RPC, ne persiste aucune donnée, ne gère pas les secrets de wallet et ne soumet aucune transaction.
|
||||||
|
|
||||||
|
Depuis `0.5.1-pre.008`, `ks-lib` ne dépend plus de TS-RS et ne génère plus de bindings TypeScript. Ses contrats Rust restent généralistes ; une application Tauri qui doit exposer une partie de ces contrats définit un DTO/wrapper applicatif explicite.
|
||||||
|
|
||||||
## Surface publique principale
|
## Surface publique principale
|
||||||
|
|
||||||
- contrats `DcApi*` et décodeurs concrets `Dc*Decoder` ;
|
- contrats `DcApi*` et décodeurs concrets `Dc*Decoder` ;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<!-- file: ks-lib/USAGE.md -->
|
<!-- file: ks-lib/USAGE.md -->
|
||||||
<!-- version: 17 -->
|
<!-- version: 18 -->
|
||||||
|
|
||||||
# Utilisation de ks-lib
|
# Utilisation de ks-lib
|
||||||
|
|
||||||
@@ -16,6 +16,8 @@ ks-lib = { path = "../ks-lib" }
|
|||||||
|
|
||||||
Toutes les fonctions retournant `ks_core::Result<T>` utilisent le contrat d’erreur structuré du workspace.
|
Toutes les fonctions retournant `ks_core::Result<T>` utilisent le contrat d’erreur structuré du workspace.
|
||||||
|
|
||||||
|
`ks-lib` n'est pas une frontière TypeScript : depuis `0.5.1-pre.008`, la crate ne dépend plus de TS-RS et ne produit plus de bindings. Les applications exposent uniquement leurs wrappers/DTO propres.
|
||||||
|
|
||||||
## Décodage contextualisé
|
## Décodage contextualisé
|
||||||
|
|
||||||
`DcApiInstructionDecoder` définit la reconnaissance et le décodage d’une instruction contextualisée. Les décodeurs concrets sont des valeurs sans état.
|
`DcApiInstructionDecoder` définit la reconnaissance et le décodage d’une instruction contextualisée. Les décodeurs concrets sont des valeurs sans état.
|
||||||
|
|||||||
@@ -1,17 +1,11 @@
|
|||||||
// file: ks-lib/src/executor/api/execution.rs
|
// file: ks-lib/src/executor/api/execution.rs
|
||||||
// version: 10
|
// version: 11
|
||||||
|
|
||||||
//! Typed execution plans, policies and result contracts.
|
//! Typed execution plans, policies and result contracts.
|
||||||
|
|
||||||
use ts_rs::TS; // rust-rules: derive-import
|
|
||||||
|
|
||||||
/// Exact capability returned for one program operation.
|
/// Exact capability returned for one program operation.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[serde(tag = "status", rename_all = "snake_case")]
|
#[serde(tag = "status", rename_all = "snake_case")]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/api/execution/ExecutionCapability.ts"
|
|
||||||
)]
|
|
||||||
pub enum ExApiExecutionCapability {
|
pub enum ExApiExecutionCapability {
|
||||||
/// The operation is implemented by the executor.
|
/// The operation is implemented by the executor.
|
||||||
Supported {
|
Supported {
|
||||||
@@ -51,12 +45,8 @@ impl crate::ExApiExecutionCapability {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Solana cluster expected by an execution plan.
|
/// Solana cluster expected by an execution plan.
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Serialize, TS)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Serialize)]
|
||||||
#[serde(rename_all = "snake_case")]
|
#[serde(rename_all = "snake_case")]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/api/execution/ExecutionCluster.ts"
|
|
||||||
)]
|
|
||||||
pub enum ExApiExecutionCluster {
|
pub enum ExApiExecutionCluster {
|
||||||
/// Local validator cluster.
|
/// Local validator cluster.
|
||||||
Localnet,
|
Localnet,
|
||||||
@@ -101,11 +91,7 @@ impl<'de> serde::Deserialize<'de> for crate::ExApiExecutionCluster {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Cluster restrictions attached to an execution plan.
|
/// Cluster restrictions attached to an execution plan.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/api/execution/ExecutionClusterPolicy.ts"
|
|
||||||
)]
|
|
||||||
pub struct ExApiExecutionClusterPolicy {
|
pub struct ExApiExecutionClusterPolicy {
|
||||||
/// Cluster that the RPC endpoint must report.
|
/// Cluster that the RPC endpoint must report.
|
||||||
pub expected_cluster: crate::ExApiExecutionCluster,
|
pub expected_cluster: crate::ExApiExecutionCluster,
|
||||||
@@ -126,12 +112,8 @@ impl std::default::Default for crate::ExApiExecutionClusterPolicy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Simulation requirement attached to an execution plan.
|
/// Simulation requirement attached to an execution plan.
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[serde(rename_all = "snake_case")]
|
#[serde(rename_all = "snake_case")]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/api/execution/ExecutionSimulationPolicy.ts"
|
|
||||||
)]
|
|
||||||
pub enum ExApiExecutionSimulationPolicy {
|
pub enum ExApiExecutionSimulationPolicy {
|
||||||
/// Simulation must succeed before signing or sending.
|
/// Simulation must succeed before signing or sending.
|
||||||
Required,
|
Required,
|
||||||
@@ -140,12 +122,8 @@ pub enum ExApiExecutionSimulationPolicy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Blockhash source required when a transaction is assembled.
|
/// Blockhash source required when a transaction is assembled.
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[serde(rename_all = "snake_case")]
|
#[serde(rename_all = "snake_case")]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/api/execution/ExecutionBlockhashKind.ts"
|
|
||||||
)]
|
|
||||||
pub enum ExApiExecutionBlockhashKind {
|
pub enum ExApiExecutionBlockhashKind {
|
||||||
/// Fetch a recent blockhash and enforce a bounded age.
|
/// Fetch a recent blockhash and enforce a bounded age.
|
||||||
Latest,
|
Latest,
|
||||||
@@ -154,11 +132,7 @@ pub enum ExApiExecutionBlockhashKind {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Blockhash or durable nonce policy attached to an execution plan.
|
/// Blockhash or durable nonce policy attached to an execution plan.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/api/execution/ExecutionBlockhashPolicy.ts"
|
|
||||||
)]
|
|
||||||
pub struct ExApiExecutionBlockhashPolicy {
|
pub struct ExApiExecutionBlockhashPolicy {
|
||||||
/// Selected blockhash source.
|
/// Selected blockhash source.
|
||||||
pub kind: crate::ExApiExecutionBlockhashKind,
|
pub kind: crate::ExApiExecutionBlockhashKind,
|
||||||
@@ -182,11 +156,7 @@ impl std::default::Default for crate::ExApiExecutionBlockhashPolicy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Explicit cost ceilings attached to an execution plan.
|
/// Explicit cost ceilings attached to an execution plan.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/api/execution/ExecutionCostLimit.ts"
|
|
||||||
)]
|
|
||||||
pub struct ExApiExecutionCostLimit {
|
pub struct ExApiExecutionCostLimit {
|
||||||
/// Maximum lamports that operation instructions may transfer or lock.
|
/// Maximum lamports that operation instructions may transfer or lock.
|
||||||
pub max_spend_lamports: std::option::Option<u64>,
|
pub max_spend_lamports: std::option::Option<u64>,
|
||||||
@@ -207,11 +177,7 @@ impl std::default::Default for crate::ExApiExecutionCostLimit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Post-execution replay validation policy.
|
/// Post-execution replay validation policy.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/api/execution/PostExecutionValidationPolicy.ts"
|
|
||||||
)]
|
|
||||||
pub struct ExApiPostExecutionValidationPolicy {
|
pub struct ExApiPostExecutionValidationPolicy {
|
||||||
/// Whether the sent signature must be inserted into canonical storage.
|
/// Whether the sent signature must be inserted into canonical storage.
|
||||||
pub canonical_insert_required: bool,
|
pub canonical_insert_required: bool,
|
||||||
@@ -235,11 +201,7 @@ impl std::default::Default for crate::ExApiPostExecutionValidationPolicy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Conservative policy carried from intent creation to transaction assembly.
|
/// Conservative policy carried from intent creation to transaction assembly.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/api/execution/ExecutionPolicy.ts"
|
|
||||||
)]
|
|
||||||
pub struct ExApiExecutionPolicy {
|
pub struct ExApiExecutionPolicy {
|
||||||
/// Cluster restrictions.
|
/// Cluster restrictions.
|
||||||
pub cluster: crate::ExApiExecutionClusterPolicy,
|
pub cluster: crate::ExApiExecutionClusterPolicy,
|
||||||
@@ -272,11 +234,7 @@ impl std::default::Default for crate::ExApiExecutionPolicy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// One account required by a planned instruction.
|
/// One account required by a planned instruction.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/api/execution/PlannedAccount.ts"
|
|
||||||
)]
|
|
||||||
pub struct ExApiPlannedAccount {
|
pub struct ExApiPlannedAccount {
|
||||||
/// Account public key.
|
/// Account public key.
|
||||||
pub pubkey: crate::MdPubkey,
|
pub pubkey: crate::MdPubkey,
|
||||||
@@ -287,11 +245,7 @@ pub struct ExApiPlannedAccount {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// One fully encoded instruction in an execution plan.
|
/// One fully encoded instruction in an execution plan.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/api/execution/PlannedInstruction.ts"
|
|
||||||
)]
|
|
||||||
pub struct ExApiPlannedInstruction {
|
pub struct ExApiPlannedInstruction {
|
||||||
/// Target program id.
|
/// Target program id.
|
||||||
pub program_id: crate::MdProgramId,
|
pub program_id: crate::MdProgramId,
|
||||||
@@ -304,11 +258,7 @@ pub struct ExApiPlannedInstruction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Signer required before transaction assembly.
|
/// Signer required before transaction assembly.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/api/execution/RequiredSigner.ts"
|
|
||||||
)]
|
|
||||||
pub struct ExApiRequiredSigner {
|
pub struct ExApiRequiredSigner {
|
||||||
/// Signer public key.
|
/// Signer public key.
|
||||||
pub pubkey: crate::MdPubkey,
|
pub pubkey: crate::MdPubkey,
|
||||||
@@ -317,11 +267,7 @@ pub struct ExApiRequiredSigner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Typed execution plan produced before transaction assembly.
|
/// Typed execution plan produced before transaction assembly.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/api/execution/PreparedExecutionPlan.ts"
|
|
||||||
)]
|
|
||||||
pub struct ExApiPreparedExecutionPlan {
|
pub struct ExApiPreparedExecutionPlan {
|
||||||
/// Stable executor crate name.
|
/// Stable executor crate name.
|
||||||
pub executor_name: std::string::String,
|
pub executor_name: std::string::String,
|
||||||
@@ -346,11 +292,7 @@ pub struct ExApiPreparedExecutionPlan {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Result returned by a transaction simulation adapter.
|
/// Result returned by a transaction simulation adapter.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/api/execution/ExecutionSimulationResult.ts"
|
|
||||||
)]
|
|
||||||
pub struct ExApiExecutionSimulationResult {
|
pub struct ExApiExecutionSimulationResult {
|
||||||
/// Whether an RPC simulation call was actually performed.
|
/// Whether an RPC simulation call was actually performed.
|
||||||
pub simulated: bool,
|
pub simulated: bool,
|
||||||
@@ -386,11 +328,7 @@ pub struct ExApiExecutionSimulationResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Result returned after an adapter submits a signed transaction.
|
/// Result returned after an adapter submits a signed transaction.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/api/execution/ExecutionSendResult.ts"
|
|
||||||
)]
|
|
||||||
pub struct ExApiExecutionSendResult {
|
pub struct ExApiExecutionSendResult {
|
||||||
/// Cluster used for submission.
|
/// Cluster used for submission.
|
||||||
pub cluster: crate::ExApiExecutionCluster,
|
pub cluster: crate::ExApiExecutionCluster,
|
||||||
@@ -401,12 +339,8 @@ pub struct ExApiExecutionSendResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Confirmation state returned by an execution confirmation adapter.
|
/// Confirmation state returned by an execution confirmation adapter.
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[serde(rename_all = "snake_case")]
|
#[serde(rename_all = "snake_case")]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/api/execution/ExecutionConfirmationStatus.ts"
|
|
||||||
)]
|
|
||||||
pub enum ExApiExecutionConfirmationStatus {
|
pub enum ExApiExecutionConfirmationStatus {
|
||||||
/// The transaction was observed at processed commitment.
|
/// The transaction was observed at processed commitment.
|
||||||
Processed,
|
Processed,
|
||||||
@@ -423,11 +357,7 @@ pub enum ExApiExecutionConfirmationStatus {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Result returned after waiting for transaction confirmation.
|
/// Result returned after waiting for transaction confirmation.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/api/execution/ExecutionConfirmationResult.ts"
|
|
||||||
)]
|
|
||||||
pub struct ExApiExecutionConfirmationResult {
|
pub struct ExApiExecutionConfirmationResult {
|
||||||
/// Cluster queried for confirmation.
|
/// Cluster queried for confirmation.
|
||||||
pub cluster: crate::ExApiExecutionCluster,
|
pub cluster: crate::ExApiExecutionCluster,
|
||||||
@@ -446,11 +376,7 @@ pub struct ExApiExecutionConfirmationResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Diagnostic produced by post-execution canonical replay validation.
|
/// Diagnostic produced by post-execution canonical replay validation.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/api/execution/PostExecutionDiagnostic.ts"
|
|
||||||
)]
|
|
||||||
pub struct ExApiPostExecutionDiagnostic {
|
pub struct ExApiPostExecutionDiagnostic {
|
||||||
/// Executed transaction signature.
|
/// Executed transaction signature.
|
||||||
pub signature: crate::MdSignature,
|
pub signature: crate::MdSignature,
|
||||||
|
|||||||
@@ -1,16 +1,10 @@
|
|||||||
// file: ks-lib/src/executor/api/executor.rs
|
// file: ks-lib/src/executor/api/executor.rs
|
||||||
// version: 5
|
// version: 6
|
||||||
|
|
||||||
//! Shared execution contract and neutral request models.
|
//! Shared execution contract and neutral request models.
|
||||||
|
|
||||||
use ts_rs::TS; // rust-rules: derive-import
|
|
||||||
|
|
||||||
/// Support level returned by an executor for a requested operation.
|
/// Support level returned by an executor for a requested operation.
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, TS)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/api/executor/ExecutionSupport.ts"
|
|
||||||
)]
|
|
||||||
pub enum ExApiExecutionSupport {
|
pub enum ExApiExecutionSupport {
|
||||||
/// The executor cannot handle the request.
|
/// The executor cannot handle the request.
|
||||||
No,
|
No,
|
||||||
@@ -21,11 +15,7 @@ pub enum ExApiExecutionSupport {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Generic request used before protocol-specific execution models are introduced.
|
/// Generic request used before protocol-specific execution models are introduced.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, TS)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/api/executor/ExecutionRequest.ts"
|
|
||||||
)]
|
|
||||||
pub struct ExApiExecutionRequest {
|
pub struct ExApiExecutionRequest {
|
||||||
/// Target program id.
|
/// Target program id.
|
||||||
pub program_id: crate::MdProgramId,
|
pub program_id: crate::MdProgramId,
|
||||||
@@ -36,11 +26,7 @@ pub struct ExApiExecutionRequest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Neutral execution plan placeholder produced by executor crates.
|
/// Neutral execution plan placeholder produced by executor crates.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, TS)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/api/executor/ExecutionPlan.ts"
|
|
||||||
)]
|
|
||||||
pub struct ExApiExecutionPlan {
|
pub struct ExApiExecutionPlan {
|
||||||
/// Stable executor crate name.
|
/// Stable executor crate name.
|
||||||
pub executor_name: std::string::String,
|
pub executor_name: std::string::String,
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
// file: ks-lib/src/executor/metadata/metaplex_token_metadata/intent.rs
|
// file: ks-lib/src/executor/metadata/metaplex_token_metadata/intent.rs
|
||||||
// version: 11
|
// version: 12
|
||||||
|
|
||||||
//! Typed current and deprecated Metaplex Token Metadata execution intents.
|
//! Typed current and deprecated Metaplex Token Metadata execution intents.
|
||||||
|
|
||||||
use ts_rs::TS; // rust-rules: derive-import
|
|
||||||
|
|
||||||
/// Stable operation code for the current Create wrapper, discriminator 42.
|
/// Stable operation code for the current Create wrapper, discriminator 42.
|
||||||
pub const EX_METAPLEX_TOKEN_METADATA_CREATE_OPERATION: &str =
|
pub const EX_METAPLEX_TOKEN_METADATA_CREATE_OPERATION: &str =
|
||||||
"metadata.metaplex_token_metadata.create";
|
"metadata.metaplex_token_metadata.create";
|
||||||
@@ -164,12 +162,8 @@ pub const EX_METAPLEX_TOKEN_METADATA_SUPPORTED_OPERATION_CODES: &[&str] = &[
|
|||||||
];
|
];
|
||||||
|
|
||||||
/// One current or explicitly deprecated Metaplex Token Metadata operation.
|
/// One current or explicitly deprecated Metaplex Token Metadata operation.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[serde(tag = "operation", rename_all = "snake_case")]
|
#[serde(tag = "operation", rename_all = "snake_case")]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/metadata/metaplex_token_metadata/intent/ExMetaplexTokenMetadataOperation.ts"
|
|
||||||
)]
|
|
||||||
pub enum ExMetaplexTokenMetadataOperation {
|
pub enum ExMetaplexTokenMetadataOperation {
|
||||||
/// Build the current Create wrapper with `CreateArgs::V1`.
|
/// Build the current Create wrapper with `CreateArgs::V1`.
|
||||||
Create {
|
Create {
|
||||||
@@ -190,7 +184,6 @@ pub enum ExMetaplexTokenMetadataOperation {
|
|||||||
/// Optional SPL Token or Token-2022 program account.
|
/// Optional SPL Token or Token-2022 program account.
|
||||||
spl_token_program: std::option::Option<crate::MdProgramId>,
|
spl_token_program: std::option::Option<crate::MdProgramId>,
|
||||||
/// Official Metaplex create arguments.
|
/// Official Metaplex create arguments.
|
||||||
#[ts(type = "unknown")]
|
|
||||||
create_args: mpl_token_metadata::types::CreateArgs,
|
create_args: mpl_token_metadata::types::CreateArgs,
|
||||||
},
|
},
|
||||||
/// Build the current Update wrapper as the update authority.
|
/// Build the current Update wrapper as the update authority.
|
||||||
@@ -210,7 +203,6 @@ pub enum ExMetaplexTokenMetadataOperation {
|
|||||||
/// Optional Token Authorization Rules account.
|
/// Optional Token Authorization Rules account.
|
||||||
authorization_rules: std::option::Option<crate::MdPubkey>,
|
authorization_rules: std::option::Option<crate::MdPubkey>,
|
||||||
/// Official Metaplex update arguments. Only `AsUpdateAuthorityV2` is accepted in this prerelease.
|
/// Official Metaplex update arguments. Only `AsUpdateAuthorityV2` is accepted in this prerelease.
|
||||||
#[ts(type = "unknown")]
|
|
||||||
update_args: mpl_token_metadata::types::UpdateArgs,
|
update_args: mpl_token_metadata::types::UpdateArgs,
|
||||||
},
|
},
|
||||||
/// Build the obsolete PuffMetadata instruction retained for compatibility workflows.
|
/// Build the obsolete PuffMetadata instruction retained for compatibility workflows.
|
||||||
@@ -252,7 +244,6 @@ pub enum ExMetaplexTokenMetadataOperation {
|
|||||||
/// Optional canonical collection master edition PDA.
|
/// Optional canonical collection master edition PDA.
|
||||||
collection_master_edition: std::option::Option<crate::MdPubkey>,
|
collection_master_edition: std::option::Option<crate::MdPubkey>,
|
||||||
/// Official unified verification variant.
|
/// Official unified verification variant.
|
||||||
#[ts(type = "unknown")]
|
|
||||||
verification_args: mpl_token_metadata::types::VerificationArgs,
|
verification_args: mpl_token_metadata::types::VerificationArgs,
|
||||||
},
|
},
|
||||||
/// Build the current unified Unverify wrapper for a creator or collection.
|
/// Build the current unified Unverify wrapper for a creator or collection.
|
||||||
@@ -268,7 +259,6 @@ pub enum ExMetaplexTokenMetadataOperation {
|
|||||||
/// Optional canonical collection metadata PDA.
|
/// Optional canonical collection metadata PDA.
|
||||||
collection_metadata: std::option::Option<crate::MdPubkey>,
|
collection_metadata: std::option::Option<crate::MdPubkey>,
|
||||||
/// Official unified verification variant.
|
/// Official unified verification variant.
|
||||||
#[ts(type = "unknown")]
|
|
||||||
verification_args: mpl_token_metadata::types::VerificationArgs,
|
verification_args: mpl_token_metadata::types::VerificationArgs,
|
||||||
},
|
},
|
||||||
/// Build obsolete SetCollectionSize retained for compatibility workflows.
|
/// Build obsolete SetCollectionSize retained for compatibility workflows.
|
||||||
@@ -302,7 +292,6 @@ pub enum ExMetaplexTokenMetadataOperation {
|
|||||||
master_edition_token: std::option::Option<crate::MdPubkey>,
|
master_edition_token: std::option::Option<crate::MdPubkey>,
|
||||||
edition_marker: std::option::Option<crate::MdPubkey>,
|
edition_marker: std::option::Option<crate::MdPubkey>,
|
||||||
token_record: std::option::Option<crate::MdPubkey>,
|
token_record: std::option::Option<crate::MdPubkey>,
|
||||||
#[ts(type = "unknown")]
|
|
||||||
burn_args: mpl_token_metadata::types::BurnArgs,
|
burn_args: mpl_token_metadata::types::BurnArgs,
|
||||||
},
|
},
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
@@ -319,7 +308,6 @@ pub enum ExMetaplexTokenMetadataOperation {
|
|||||||
spl_token_program: std::option::Option<crate::MdProgramId>,
|
spl_token_program: std::option::Option<crate::MdProgramId>,
|
||||||
authorization_rules_program: std::option::Option<crate::MdProgramId>,
|
authorization_rules_program: std::option::Option<crate::MdProgramId>,
|
||||||
authorization_rules: std::option::Option<crate::MdPubkey>,
|
authorization_rules: std::option::Option<crate::MdPubkey>,
|
||||||
#[ts(type = "unknown")]
|
|
||||||
delegate_args: mpl_token_metadata::types::DelegateArgs,
|
delegate_args: mpl_token_metadata::types::DelegateArgs,
|
||||||
},
|
},
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
@@ -336,7 +324,6 @@ pub enum ExMetaplexTokenMetadataOperation {
|
|||||||
spl_token_program: std::option::Option<crate::MdProgramId>,
|
spl_token_program: std::option::Option<crate::MdProgramId>,
|
||||||
authorization_rules_program: std::option::Option<crate::MdProgramId>,
|
authorization_rules_program: std::option::Option<crate::MdProgramId>,
|
||||||
authorization_rules: std::option::Option<crate::MdPubkey>,
|
authorization_rules: std::option::Option<crate::MdPubkey>,
|
||||||
#[ts(type = "unknown")]
|
|
||||||
revoke_args: mpl_token_metadata::types::RevokeArgs,
|
revoke_args: mpl_token_metadata::types::RevokeArgs,
|
||||||
},
|
},
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
@@ -352,7 +339,6 @@ pub enum ExMetaplexTokenMetadataOperation {
|
|||||||
spl_token_program: std::option::Option<crate::MdProgramId>,
|
spl_token_program: std::option::Option<crate::MdProgramId>,
|
||||||
authorization_rules_program: std::option::Option<crate::MdProgramId>,
|
authorization_rules_program: std::option::Option<crate::MdProgramId>,
|
||||||
authorization_rules: std::option::Option<crate::MdPubkey>,
|
authorization_rules: std::option::Option<crate::MdPubkey>,
|
||||||
#[ts(type = "unknown")]
|
|
||||||
lock_args: mpl_token_metadata::types::LockArgs,
|
lock_args: mpl_token_metadata::types::LockArgs,
|
||||||
},
|
},
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
@@ -368,7 +354,6 @@ pub enum ExMetaplexTokenMetadataOperation {
|
|||||||
spl_token_program: std::option::Option<crate::MdProgramId>,
|
spl_token_program: std::option::Option<crate::MdProgramId>,
|
||||||
authorization_rules_program: std::option::Option<crate::MdProgramId>,
|
authorization_rules_program: std::option::Option<crate::MdProgramId>,
|
||||||
authorization_rules: std::option::Option<crate::MdPubkey>,
|
authorization_rules: std::option::Option<crate::MdPubkey>,
|
||||||
#[ts(type = "unknown")]
|
|
||||||
unlock_args: mpl_token_metadata::types::UnlockArgs,
|
unlock_args: mpl_token_metadata::types::UnlockArgs,
|
||||||
},
|
},
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
@@ -386,7 +371,6 @@ pub enum ExMetaplexTokenMetadataOperation {
|
|||||||
authority: crate::MdPubkey,
|
authority: crate::MdPubkey,
|
||||||
authorization_rules_program: std::option::Option<crate::MdProgramId>,
|
authorization_rules_program: std::option::Option<crate::MdProgramId>,
|
||||||
authorization_rules: std::option::Option<crate::MdPubkey>,
|
authorization_rules: std::option::Option<crate::MdPubkey>,
|
||||||
#[ts(type = "unknown")]
|
|
||||||
transfer_args: mpl_token_metadata::types::TransferArgs,
|
transfer_args: mpl_token_metadata::types::TransferArgs,
|
||||||
},
|
},
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
@@ -619,7 +603,6 @@ pub enum ExMetaplexTokenMetadataOperation {
|
|||||||
/// Account `rent` from the official IDL contract.
|
/// Account `rent` from the official IDL contract.
|
||||||
rent: crate::MdPubkey,
|
rent: crate::MdPubkey,
|
||||||
/// Official Metaplex instruction arguments.
|
/// Official Metaplex instruction arguments.
|
||||||
#[ts(type = "unknown")]
|
|
||||||
args: mpl_token_metadata::types::MintNewEditionFromMasterEditionViaTokenArgs,
|
args: mpl_token_metadata::types::MintNewEditionFromMasterEditionViaTokenArgs,
|
||||||
},
|
},
|
||||||
/// Build deprecated Utilize, retained for explicit compatibility workflows.
|
/// Build deprecated Utilize, retained for explicit compatibility workflows.
|
||||||
@@ -651,7 +634,6 @@ pub enum ExMetaplexTokenMetadataOperation {
|
|||||||
/// Account `burner` from the official IDL contract.
|
/// Account `burner` from the official IDL contract.
|
||||||
burner: crate::MdPubkey,
|
burner: crate::MdPubkey,
|
||||||
/// Official Metaplex instruction arguments.
|
/// Official Metaplex instruction arguments.
|
||||||
#[ts(type = "unknown")]
|
|
||||||
args: mpl_token_metadata::instructions::UtilizeInstructionArgs,
|
args: mpl_token_metadata::instructions::UtilizeInstructionArgs,
|
||||||
},
|
},
|
||||||
/// Build deprecated ApproveUseAuthority, retained for explicit compatibility workflows.
|
/// Build deprecated ApproveUseAuthority, retained for explicit compatibility workflows.
|
||||||
@@ -683,7 +665,6 @@ pub enum ExMetaplexTokenMetadataOperation {
|
|||||||
/// Account `rent` from the official IDL contract.
|
/// Account `rent` from the official IDL contract.
|
||||||
rent: crate::MdPubkey,
|
rent: crate::MdPubkey,
|
||||||
/// Official Metaplex instruction arguments.
|
/// Official Metaplex instruction arguments.
|
||||||
#[ts(type = "unknown")]
|
|
||||||
args: mpl_token_metadata::instructions::ApproveUseAuthorityInstructionArgs,
|
args: mpl_token_metadata::instructions::ApproveUseAuthorityInstructionArgs,
|
||||||
},
|
},
|
||||||
/// Build deprecated RevokeUseAuthority, retained for explicit compatibility workflows.
|
/// Build deprecated RevokeUseAuthority, retained for explicit compatibility workflows.
|
||||||
@@ -780,7 +761,6 @@ pub enum ExMetaplexTokenMetadataOperation {
|
|||||||
/// Optional authority from the current SDK contract.
|
/// Optional authority from the current SDK contract.
|
||||||
authority: std::option::Option<crate::MdPubkey>,
|
authority: std::option::Option<crate::MdPubkey>,
|
||||||
/// Official Metaplex instruction arguments.
|
/// Official Metaplex instruction arguments.
|
||||||
#[ts(type = "unknown")]
|
|
||||||
args: mpl_token_metadata::instructions::TransferOutOfEscrowInstructionArgs,
|
args: mpl_token_metadata::instructions::TransferOutOfEscrowInstructionArgs,
|
||||||
},
|
},
|
||||||
/// Build the current Mint instruction.
|
/// Build the current Mint instruction.
|
||||||
@@ -816,7 +796,6 @@ pub enum ExMetaplexTokenMetadataOperation {
|
|||||||
/// Optional Token Authorization Rules account in the current SDK contract.
|
/// Optional Token Authorization Rules account in the current SDK contract.
|
||||||
authorization_rules: std::option::Option<crate::MdPubkey>,
|
authorization_rules: std::option::Option<crate::MdPubkey>,
|
||||||
/// Official Metaplex instruction arguments.
|
/// Official Metaplex instruction arguments.
|
||||||
#[ts(type = "unknown")]
|
|
||||||
args: mpl_token_metadata::types::MintArgs,
|
args: mpl_token_metadata::types::MintArgs,
|
||||||
},
|
},
|
||||||
/// Build the current Migrate instruction.
|
/// Build the current Migrate instruction.
|
||||||
@@ -879,7 +858,6 @@ pub enum ExMetaplexTokenMetadataOperation {
|
|||||||
/// Optional Token Authorization Rules account in the current SDK contract.
|
/// Optional Token Authorization Rules account in the current SDK contract.
|
||||||
authorization_rules: std::option::Option<crate::MdPubkey>,
|
authorization_rules: std::option::Option<crate::MdPubkey>,
|
||||||
/// Official Metaplex instruction arguments.
|
/// Official Metaplex instruction arguments.
|
||||||
#[ts(type = "unknown")]
|
|
||||||
args: mpl_token_metadata::types::UseArgs,
|
args: mpl_token_metadata::types::UseArgs,
|
||||||
},
|
},
|
||||||
/// Build the current Collect instruction.
|
/// Build the current Collect instruction.
|
||||||
@@ -928,7 +906,6 @@ pub enum ExMetaplexTokenMetadataOperation {
|
|||||||
/// Account `systemProgram` from the official IDL contract.
|
/// Account `systemProgram` from the official IDL contract.
|
||||||
system_program: crate::MdPubkey,
|
system_program: crate::MdPubkey,
|
||||||
/// Official Metaplex instruction arguments.
|
/// Official Metaplex instruction arguments.
|
||||||
#[ts(type = "unknown")]
|
|
||||||
args: mpl_token_metadata::types::PrintArgs,
|
args: mpl_token_metadata::types::PrintArgs,
|
||||||
},
|
},
|
||||||
/// Build the current Resize instruction.
|
/// Build the current Resize instruction.
|
||||||
@@ -1027,11 +1004,7 @@ impl crate::ExMetaplexTokenMetadataOperation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Complete typed intent accepted by the Metaplex Token Metadata executor.
|
/// Complete typed intent accepted by the Metaplex Token Metadata executor.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/metadata/metaplex_token_metadata/intent/ExMetaplexTokenMetadataExecutionIntent.ts"
|
|
||||||
)]
|
|
||||||
pub struct ExMetaplexTokenMetadataExecutionIntent {
|
pub struct ExMetaplexTokenMetadataExecutionIntent {
|
||||||
/// Stable caller-provided identifier used for logs and replay correlation.
|
/// Stable caller-provided identifier used for logs and replay correlation.
|
||||||
pub intent_id: std::string::String,
|
pub intent_id: std::string::String,
|
||||||
|
|||||||
@@ -1,18 +1,12 @@
|
|||||||
// file: ks-lib/src/executor/metadata/solana_program_metadata/intent.rs
|
// file: ks-lib/src/executor/metadata/solana_program_metadata/intent.rs
|
||||||
// version: 2
|
// version: 3
|
||||||
|
|
||||||
//! Typed intents for the Solana Program Metadata executor.
|
//! Typed intents for the Solana Program Metadata executor.
|
||||||
|
|
||||||
use ts_rs::TS; // rust-rules: derive-import
|
|
||||||
|
|
||||||
/// Encoding written to a Solana Program Metadata account.
|
/// Encoding written to a Solana Program Metadata account.
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
#[serde(rename_all = "snake_case")]
|
#[serde(rename_all = "snake_case")]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/metadata/solana_program_metadata/intent/ExMetadataSpmEncoding.ts"
|
|
||||||
)]
|
|
||||||
pub enum ExMetadataSpmEncoding {
|
pub enum ExMetadataSpmEncoding {
|
||||||
/// No encoding declaration.
|
/// No encoding declaration.
|
||||||
None = 0,
|
None = 0,
|
||||||
@@ -32,13 +26,9 @@ impl crate::ExMetadataSpmEncoding {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Compression written to a Solana Program Metadata account.
|
/// Compression written to a Solana Program Metadata account.
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
#[serde(rename_all = "snake_case")]
|
#[serde(rename_all = "snake_case")]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/metadata/solana_program_metadata/intent/ExMetadataSpmCompression.ts"
|
|
||||||
)]
|
|
||||||
pub enum ExMetadataSpmCompression {
|
pub enum ExMetadataSpmCompression {
|
||||||
/// No compression declaration.
|
/// No compression declaration.
|
||||||
None = 0,
|
None = 0,
|
||||||
@@ -56,13 +46,9 @@ impl crate::ExMetadataSpmCompression {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Structured format written to a Solana Program Metadata account.
|
/// Structured format written to a Solana Program Metadata account.
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
#[serde(rename_all = "snake_case")]
|
#[serde(rename_all = "snake_case")]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/metadata/solana_program_metadata/intent/ExMetadataSpmFormat.ts"
|
|
||||||
)]
|
|
||||||
pub enum ExMetadataSpmFormat {
|
pub enum ExMetadataSpmFormat {
|
||||||
/// No structured format declaration.
|
/// No structured format declaration.
|
||||||
None = 0,
|
None = 0,
|
||||||
@@ -82,13 +68,9 @@ impl crate::ExMetadataSpmFormat {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// On-chain data source written to a Solana Program Metadata account.
|
/// On-chain data source written to a Solana Program Metadata account.
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
#[serde(rename_all = "snake_case")]
|
#[serde(rename_all = "snake_case")]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/metadata/solana_program_metadata/intent/ExMetadataSpmDataSource.ts"
|
|
||||||
)]
|
|
||||||
pub enum ExMetadataSpmDataSource {
|
pub enum ExMetadataSpmDataSource {
|
||||||
/// Direct on-chain bytes.
|
/// Direct on-chain bytes.
|
||||||
Direct = 0,
|
Direct = 0,
|
||||||
@@ -106,12 +88,8 @@ impl crate::ExMetadataSpmDataSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Exact inline content accepted by `Initialize` and `SetData`.
|
/// Exact inline content accepted by `Initialize` and `SetData`.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[serde(tag = "source", rename_all = "snake_case")]
|
#[serde(tag = "source", rename_all = "snake_case")]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/metadata/solana_program_metadata/intent/ExMetadataSpmDataInput.ts"
|
|
||||||
)]
|
|
||||||
pub enum ExMetadataSpmDataInput {
|
pub enum ExMetadataSpmDataInput {
|
||||||
/// Direct on-chain bytes.
|
/// Direct on-chain bytes.
|
||||||
Direct {
|
Direct {
|
||||||
@@ -148,12 +126,8 @@ impl crate::ExMetadataSpmDataInput {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Source used by the `Write` instruction.
|
/// Source used by the `Write` instruction.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[serde(tag = "source", rename_all = "snake_case")]
|
#[serde(tag = "source", rename_all = "snake_case")]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/metadata/solana_program_metadata/intent/ExMetadataSpmWriteSource.ts"
|
|
||||||
)]
|
|
||||||
pub enum ExMetadataSpmWriteSource {
|
pub enum ExMetadataSpmWriteSource {
|
||||||
/// Inline bytes placed after the offset argument.
|
/// Inline bytes placed after the offset argument.
|
||||||
Inline {
|
Inline {
|
||||||
@@ -168,12 +142,8 @@ pub enum ExMetadataSpmWriteSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Source used by the `SetData` instruction.
|
/// Source used by the `SetData` instruction.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[serde(tag = "source", rename_all = "snake_case")]
|
#[serde(tag = "source", rename_all = "snake_case")]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/metadata/solana_program_metadata/intent/ExMetadataSpmSetDataSource.ts"
|
|
||||||
)]
|
|
||||||
pub enum ExMetadataSpmSetDataSource {
|
pub enum ExMetadataSpmSetDataSource {
|
||||||
/// Runtime-supported three-byte variant that preserves current data bytes.
|
/// Runtime-supported three-byte variant that preserves current data bytes.
|
||||||
PreserveExisting,
|
PreserveExisting,
|
||||||
@@ -192,11 +162,7 @@ pub enum ExMetadataSpmSetDataSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Optional program-upgrade-authority validation context.
|
/// Optional program-upgrade-authority validation context.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/metadata/solana_program_metadata/intent/ExMetadataSpmProgramContext.ts"
|
|
||||||
)]
|
|
||||||
pub struct ExMetadataSpmProgramContext {
|
pub struct ExMetadataSpmProgramContext {
|
||||||
/// Executable program account.
|
/// Executable program account.
|
||||||
pub program: crate::MdPubkey,
|
pub program: crate::MdPubkey,
|
||||||
@@ -205,12 +171,8 @@ pub struct ExMetadataSpmProgramContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// One exact Solana Program Metadata operation.
|
/// One exact Solana Program Metadata operation.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[serde(tag = "operation", rename_all = "snake_case")]
|
#[serde(tag = "operation", rename_all = "snake_case")]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/metadata/solana_program_metadata/intent/ExMetadataSpmOperation.ts"
|
|
||||||
)]
|
|
||||||
pub enum ExMetadataSpmOperation {
|
pub enum ExMetadataSpmOperation {
|
||||||
/// Write bytes to a Buffer account.
|
/// Write bytes to a Buffer account.
|
||||||
Write {
|
Write {
|
||||||
@@ -452,11 +414,7 @@ impl crate::ExMetadataSpmOperation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Complete Solana Program Metadata execution intent.
|
/// Complete Solana Program Metadata execution intent.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/metadata/solana_program_metadata/intent/ExMetadataSpmExecutionIntent.ts"
|
|
||||||
)]
|
|
||||||
pub struct ExMetadataSpmExecutionIntent {
|
pub struct ExMetadataSpmExecutionIntent {
|
||||||
/// Caller-provided correlation identifier.
|
/// Caller-provided correlation identifier.
|
||||||
pub intent_id: std::string::String,
|
pub intent_id: std::string::String,
|
||||||
|
|||||||
@@ -1,17 +1,11 @@
|
|||||||
// file: ks-lib/src/executor/safety/evaluation.rs
|
// file: ks-lib/src/executor/safety/evaluation.rs
|
||||||
// version: 4
|
// version: 5
|
||||||
|
|
||||||
//! Safety checks applied before simulation, signing or sending.
|
//! Safety checks applied before simulation, signing or sending.
|
||||||
|
|
||||||
use ts_rs::TS; // rust-rules: derive-import
|
|
||||||
|
|
||||||
/// Safety decision returned before continuing an execution stage.
|
/// Safety decision returned before continuing an execution stage.
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[serde(rename_all = "snake_case")]
|
#[serde(rename_all = "snake_case")]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/safety/evaluation/ExSafetyDecision.ts"
|
|
||||||
)]
|
|
||||||
pub enum ExSafetyDecision {
|
pub enum ExSafetyDecision {
|
||||||
/// The plan is not allowed to continue.
|
/// The plan is not allowed to continue.
|
||||||
Deny,
|
Deny,
|
||||||
@@ -22,11 +16,7 @@ pub enum ExSafetyDecision {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// One stable safety policy violation.
|
/// One stable safety policy violation.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/safety/evaluation/ExSafetyViolation.ts"
|
|
||||||
)]
|
|
||||||
pub struct ExSafetyViolation {
|
pub struct ExSafetyViolation {
|
||||||
/// Stable violation code.
|
/// Stable violation code.
|
||||||
pub code: std::string::String,
|
pub code: std::string::String,
|
||||||
@@ -35,11 +25,7 @@ pub struct ExSafetyViolation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Complete safety evaluation for one execution stage.
|
/// Complete safety evaluation for one execution stage.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/safety/evaluation/ExSafetyEvaluation.ts"
|
|
||||||
)]
|
|
||||||
pub struct ExSafetyEvaluation {
|
pub struct ExSafetyEvaluation {
|
||||||
/// Aggregate decision.
|
/// Aggregate decision.
|
||||||
pub decision: crate::ExSafetyDecision,
|
pub decision: crate::ExSafetyDecision,
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
// file: ks-lib/src/executor/solana/core/intent.rs
|
// file: ks-lib/src/executor/solana/core/intent.rs
|
||||||
// version: 3
|
// version: 4
|
||||||
|
|
||||||
//! Typed Solana core execution intents.
|
//! Typed Solana core execution intents.
|
||||||
|
|
||||||
use ts_rs::TS; // rust-rules: derive-import
|
|
||||||
|
|
||||||
/// Stable operation code for a System Program lamport transfer.
|
/// Stable operation code for a System Program lamport transfer.
|
||||||
pub const EX_SOLANA_CORE_SYSTEM_TRANSFER_OPERATION: &str = "solana.core.system.transfer";
|
pub const EX_SOLANA_CORE_SYSTEM_TRANSFER_OPERATION: &str = "solana.core.system.transfer";
|
||||||
/// Stable operation code for a bounded batch of System Program transfers.
|
/// Stable operation code for a bounded batch of System Program transfers.
|
||||||
@@ -412,11 +410,7 @@ pub const EX_SOLANA_CORE_OPERATION_CODES: [&str; 109] = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
/// One destination in a System Program multi-transfer.
|
/// One destination in a System Program multi-transfer.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/solana/core/intent/ExSolanaCoreSystemTransferRecipient.ts"
|
|
||||||
)]
|
|
||||||
pub struct ExSolanaCoreSystemTransferRecipient {
|
pub struct ExSolanaCoreSystemTransferRecipient {
|
||||||
/// Recipient account.
|
/// Recipient account.
|
||||||
pub to: crate::MdPubkey,
|
pub to: crate::MdPubkey,
|
||||||
@@ -425,11 +419,7 @@ pub struct ExSolanaCoreSystemTransferRecipient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// One Ed25519 signature verification offset record.
|
/// One Ed25519 signature verification offset record.
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/solana/core/intent/ExSolanaCoreEd25519VerificationOffsets.ts"
|
|
||||||
)]
|
|
||||||
pub struct ExSolanaCoreEd25519VerificationOffsets {
|
pub struct ExSolanaCoreEd25519VerificationOffsets {
|
||||||
/// Offset to the 64-byte signature.
|
/// Offset to the 64-byte signature.
|
||||||
pub signature_offset: u16,
|
pub signature_offset: u16,
|
||||||
@@ -448,11 +438,7 @@ pub struct ExSolanaCoreEd25519VerificationOffsets {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// One secp256k1 signature verification offset record.
|
/// One secp256k1 signature verification offset record.
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/solana/core/intent/ExSolanaCoreSecp256k1VerificationOffsets.ts"
|
|
||||||
)]
|
|
||||||
pub struct ExSolanaCoreSecp256k1VerificationOffsets {
|
pub struct ExSolanaCoreSecp256k1VerificationOffsets {
|
||||||
/// Offset to the 64-byte signature followed by its one-byte recovery id.
|
/// Offset to the 64-byte signature followed by its one-byte recovery id.
|
||||||
pub signature_offset: u16,
|
pub signature_offset: u16,
|
||||||
@@ -471,11 +457,7 @@ pub struct ExSolanaCoreSecp256k1VerificationOffsets {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// One secp256r1 signature verification offset record.
|
/// One secp256r1 signature verification offset record.
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/solana/core/intent/ExSolanaCoreSecp256r1VerificationOffsets.ts"
|
|
||||||
)]
|
|
||||||
pub struct ExSolanaCoreSecp256r1VerificationOffsets {
|
pub struct ExSolanaCoreSecp256r1VerificationOffsets {
|
||||||
/// Offset to the compact 64-byte signature.
|
/// Offset to the compact 64-byte signature.
|
||||||
pub signature_offset: u16,
|
pub signature_offset: u16,
|
||||||
@@ -494,12 +476,8 @@ pub struct ExSolanaCoreSecp256r1VerificationOffsets {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Stake authority role changed by an authorize instruction.
|
/// Stake authority role changed by an authorize instruction.
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[serde(rename_all = "snake_case")]
|
#[serde(rename_all = "snake_case")]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/solana/core/intent/ExSolanaCoreStakeAuthorizationKind.ts"
|
|
||||||
)]
|
|
||||||
pub enum ExSolanaCoreStakeAuthorizationKind {
|
pub enum ExSolanaCoreStakeAuthorizationKind {
|
||||||
/// Staker authority controlling delegation and stake movement.
|
/// Staker authority controlling delegation and stake movement.
|
||||||
Staker,
|
Staker,
|
||||||
@@ -517,12 +495,8 @@ impl crate::ExSolanaCoreStakeAuthorizationKind {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Vote authority role changed by an authorize instruction.
|
/// Vote authority role changed by an authorize instruction.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[serde(tag = "kind", rename_all = "snake_case")]
|
#[serde(tag = "kind", rename_all = "snake_case")]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/solana/core/intent/ExSolanaCoreVoteAuthorizationKind.ts"
|
|
||||||
)]
|
|
||||||
pub enum ExSolanaCoreVoteAuthorizationKind {
|
pub enum ExSolanaCoreVoteAuthorizationKind {
|
||||||
/// Vote authority using an Ed25519 public key.
|
/// Vote authority using an Ed25519 public key.
|
||||||
Voter,
|
Voter,
|
||||||
@@ -538,12 +512,8 @@ pub enum ExSolanaCoreVoteAuthorizationKind {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Vote v2 commission category.
|
/// Vote v2 commission category.
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[serde(rename_all = "snake_case")]
|
#[serde(rename_all = "snake_case")]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/solana/core/intent/ExSolanaCoreVoteCommissionKind.ts"
|
|
||||||
)]
|
|
||||||
pub enum ExSolanaCoreVoteCommissionKind {
|
pub enum ExSolanaCoreVoteCommissionKind {
|
||||||
/// Inflation-reward commission.
|
/// Inflation-reward commission.
|
||||||
InflationRewards,
|
InflationRewards,
|
||||||
@@ -563,11 +533,7 @@ impl crate::ExSolanaCoreVoteCommissionKind {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// One lockout entry used by Vote-state and tower synchronization instructions.
|
/// One lockout entry used by Vote-state and tower synchronization instructions.
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/solana/core/intent/ExSolanaCoreVoteLockout.ts"
|
|
||||||
)]
|
|
||||||
pub struct ExSolanaCoreVoteLockout {
|
pub struct ExSolanaCoreVoteLockout {
|
||||||
/// Voted slot.
|
/// Voted slot.
|
||||||
pub slot: u64,
|
pub slot: u64,
|
||||||
@@ -576,11 +542,7 @@ pub struct ExSolanaCoreVoteLockout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// One key entry serialized in the Config Program `ConfigKeys` short vector.
|
/// One key entry serialized in the Config Program `ConfigKeys` short vector.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/solana/core/intent/ExSolanaCoreConfigKey.ts"
|
|
||||||
)]
|
|
||||||
pub struct ExSolanaCoreConfigKey {
|
pub struct ExSolanaCoreConfigKey {
|
||||||
/// Public key stored in the Config Program key list.
|
/// Public key stored in the Config Program key list.
|
||||||
pub pubkey: crate::MdPubkey,
|
pub pubkey: crate::MdPubkey,
|
||||||
@@ -589,11 +551,7 @@ pub struct ExSolanaCoreConfigKey {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Optional context-state accounts attached to a ZK ElGamal proof verification.
|
/// Optional context-state accounts attached to a ZK ElGamal proof verification.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/solana/core/intent/ExSolanaCoreZkElGamalContextState.ts"
|
|
||||||
)]
|
|
||||||
pub struct ExSolanaCoreZkElGamalContextState {
|
pub struct ExSolanaCoreZkElGamalContextState {
|
||||||
/// Preallocated writable context-state account.
|
/// Preallocated writable context-state account.
|
||||||
pub account: crate::MdPubkey,
|
pub account: crate::MdPubkey,
|
||||||
@@ -602,12 +560,8 @@ pub struct ExSolanaCoreZkElGamalContextState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Official proof kinds accepted by the native ZK ElGamal Proof program.
|
/// Official proof kinds accepted by the native ZK ElGamal Proof program.
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[serde(rename_all = "snake_case")]
|
#[serde(rename_all = "snake_case")]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/solana/core/intent/ExSolanaCoreZkElGamalProofType.ts"
|
|
||||||
)]
|
|
||||||
pub enum ExSolanaCoreZkElGamalProofType {
|
pub enum ExSolanaCoreZkElGamalProofType {
|
||||||
/// Zero-ciphertext proof.
|
/// Zero-ciphertext proof.
|
||||||
ZeroCiphertext,
|
ZeroCiphertext,
|
||||||
@@ -732,12 +686,8 @@ impl crate::ExSolanaCoreZkElGamalProofType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Typed Solana core operation arguments.
|
/// Typed Solana core operation arguments.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[serde(tag = "operation", rename_all = "snake_case")]
|
#[serde(tag = "operation", rename_all = "snake_case")]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/solana/core/intent/ExSolanaCoreOperation.ts"
|
|
||||||
)]
|
|
||||||
pub enum ExSolanaCoreOperation {
|
pub enum ExSolanaCoreOperation {
|
||||||
/// Transfer lamports between System Program accounts.
|
/// Transfer lamports between System Program accounts.
|
||||||
SystemTransfer {
|
SystemTransfer {
|
||||||
@@ -2449,11 +2399,7 @@ impl crate::ExSolanaCoreOperation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Complete typed intent accepted by the Solana core executor.
|
/// Complete typed intent accepted by the Solana core executor.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/solana/core/intent/ExSolanaCoreExecutionIntent.ts"
|
|
||||||
)]
|
|
||||||
pub struct ExSolanaCoreExecutionIntent {
|
pub struct ExSolanaCoreExecutionIntent {
|
||||||
/// Stable caller-provided identifier used for logs and replay correlation.
|
/// Stable caller-provided identifier used for logs and replay correlation.
|
||||||
pub intent_id: std::string::String,
|
pub intent_id: std::string::String,
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
// file: ks-lib/src/executor/spl/associated_token_account/intent.rs
|
// file: ks-lib/src/executor/spl/associated_token_account/intent.rs
|
||||||
// version: 6
|
// version: 7
|
||||||
|
|
||||||
//! Typed SPL Associated Token Account execution intents.
|
//! Typed SPL Associated Token Account execution intents.
|
||||||
|
|
||||||
use ts_rs::TS; // rust-rules: derive-import
|
|
||||||
|
|
||||||
/// Stable operation code for strict ATA creation.
|
/// Stable operation code for strict ATA creation.
|
||||||
pub const EX_SPL_ATA_CREATE_OPERATION: &str = "spl.associated_token_account.create";
|
pub const EX_SPL_ATA_CREATE_OPERATION: &str = "spl.associated_token_account.create";
|
||||||
/// Stable operation code for idempotent ATA creation or reuse.
|
/// Stable operation code for idempotent ATA creation or reuse.
|
||||||
@@ -20,18 +18,13 @@ pub const EX_SPL_ATA_SUPPORTED_OPERATION_CODES: &[&str] = &[
|
|||||||
];
|
];
|
||||||
|
|
||||||
/// Exact Token Program targeted by ATA derivation and runtime CPIs.
|
/// Exact Token Program targeted by ATA derivation and runtime CPIs.
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[serde(rename_all = "snake_case")]
|
#[serde(rename_all = "snake_case")]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/spl/associated_token_account/intent/ExSplAssociatedTokenProgram.ts"
|
|
||||||
)]
|
|
||||||
pub enum ExSplAssociatedTokenProgram {
|
pub enum ExSplAssociatedTokenProgram {
|
||||||
/// Classic SPL Token program.
|
/// Classic SPL Token program.
|
||||||
Classic,
|
Classic,
|
||||||
/// Token-2022 program without extension-specific executor semantics.
|
/// Token-2022 program without extension-specific executor semantics.
|
||||||
#[serde(rename = "token_2022")]
|
#[serde(rename = "token_2022")]
|
||||||
#[ts(rename = "token_2022")]
|
|
||||||
Token2022,
|
Token2022,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,12 +39,8 @@ impl crate::ExSplAssociatedTokenProgram {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// One officially constructible ATA operation.
|
/// One officially constructible ATA operation.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[serde(tag = "operation", rename_all = "snake_case")]
|
#[serde(tag = "operation", rename_all = "snake_case")]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/spl/associated_token_account/intent/ExSplAssociatedTokenAccountOperation.ts"
|
|
||||||
)]
|
|
||||||
pub enum ExSplAssociatedTokenAccountOperation {
|
pub enum ExSplAssociatedTokenAccountOperation {
|
||||||
/// Strictly create an absent canonical ATA.
|
/// Strictly create an absent canonical ATA.
|
||||||
Create {
|
Create {
|
||||||
@@ -109,11 +98,7 @@ impl crate::ExSplAssociatedTokenAccountOperation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Complete typed intent accepted by the ATA executor.
|
/// Complete typed intent accepted by the ATA executor.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/spl/associated_token_account/intent/ExSplAssociatedTokenAccountExecutionIntent.ts"
|
|
||||||
)]
|
|
||||||
pub struct ExSplAssociatedTokenAccountExecutionIntent {
|
pub struct ExSplAssociatedTokenAccountExecutionIntent {
|
||||||
/// Stable caller-provided identifier used for logs and replay correlation.
|
/// Stable caller-provided identifier used for logs and replay correlation.
|
||||||
pub intent_id: std::string::String,
|
pub intent_id: std::string::String,
|
||||||
|
|||||||
@@ -1,22 +1,16 @@
|
|||||||
// file: ks-lib/src/executor/spl/elgamal_registry/intent.rs
|
// file: ks-lib/src/executor/spl/elgamal_registry/intent.rs
|
||||||
// version: 4
|
// version: 5
|
||||||
|
|
||||||
//! Typed intents for the SPL ElGamal public-key registry.
|
//! Typed intents for the SPL ElGamal public-key registry.
|
||||||
|
|
||||||
use ts_rs::TS; // rust-rules: derive-import
|
|
||||||
|
|
||||||
/// Stable operation code for registry creation.
|
/// Stable operation code for registry creation.
|
||||||
pub const EX_SPL_ELGAMAL_REGISTRY_CREATE_OPERATION: &str = "spl.elgamal_registry.create_registry";
|
pub const EX_SPL_ELGAMAL_REGISTRY_CREATE_OPERATION: &str = "spl.elgamal_registry.create_registry";
|
||||||
/// Stable operation code for registry update.
|
/// Stable operation code for registry update.
|
||||||
pub const EX_SPL_ELGAMAL_REGISTRY_UPDATE_OPERATION: &str = "spl.elgamal_registry.update_registry";
|
pub const EX_SPL_ELGAMAL_REGISTRY_UPDATE_OPERATION: &str = "spl.elgamal_registry.update_registry";
|
||||||
|
|
||||||
/// Exact location of the public-key validity proof.
|
/// Exact location of the public-key validity proof.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[serde(tag = "location", rename_all = "snake_case")]
|
#[serde(tag = "location", rename_all = "snake_case")]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/spl/elgamal_registry/intent/ExSplElgamalRegistryProofLocation.ts"
|
|
||||||
)]
|
|
||||||
pub enum ExSplElgamalRegistryProofLocation {
|
pub enum ExSplElgamalRegistryProofLocation {
|
||||||
/// A pre-verified proof context-state account.
|
/// A pre-verified proof context-state account.
|
||||||
ContextStateAccount {
|
ContextStateAccount {
|
||||||
@@ -31,12 +25,8 @@ pub enum ExSplElgamalRegistryProofLocation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Typed registry operation.
|
/// Typed registry operation.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[serde(tag = "operation", rename_all = "snake_case")]
|
#[serde(tag = "operation", rename_all = "snake_case")]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/spl/elgamal_registry/intent/ExSplElgamalRegistryOperation.ts"
|
|
||||||
)]
|
|
||||||
pub enum ExSplElgamalRegistryOperation {
|
pub enum ExSplElgamalRegistryOperation {
|
||||||
/// Create the deterministic registry PDA for one owner.
|
/// Create the deterministic registry PDA for one owner.
|
||||||
CreateRegistry {
|
CreateRegistry {
|
||||||
@@ -69,11 +59,7 @@ impl crate::ExSplElgamalRegistryOperation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Complete typed execution intent.
|
/// Complete typed execution intent.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/spl/elgamal_registry/intent/ExSplElgamalRegistryExecutionIntent.ts"
|
|
||||||
)]
|
|
||||||
pub struct ExSplElgamalRegistryExecutionIntent {
|
pub struct ExSplElgamalRegistryExecutionIntent {
|
||||||
/// Caller-provided correlation identifier.
|
/// Caller-provided correlation identifier.
|
||||||
pub intent_id: std::string::String,
|
pub intent_id: std::string::String,
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
// file: ks-lib/src/executor/spl/memo/intent.rs
|
// file: ks-lib/src/executor/spl/memo/intent.rs
|
||||||
// version: 3
|
// version: 4
|
||||||
|
|
||||||
//! Typed SPL Memo execution intents.
|
//! Typed SPL Memo execution intents.
|
||||||
|
|
||||||
use ts_rs::TS; // rust-rules: derive-import
|
|
||||||
|
|
||||||
/// Stable operation code for adding one SPL Memo annotation.
|
/// Stable operation code for adding one SPL Memo annotation.
|
||||||
pub const EX_SPL_MEMO_ADD_MEMO_OPERATION: &str = "spl.memo.add_memo";
|
pub const EX_SPL_MEMO_ADD_MEMO_OPERATION: &str = "spl.memo.add_memo";
|
||||||
/// Conservative UTF-8 payload bound used before transaction assembly.
|
/// Conservative UTF-8 payload bound used before transaction assembly.
|
||||||
@@ -13,12 +11,8 @@ pub const EX_SPL_MEMO_MAX_MESSAGE_BYTES: usize = 566;
|
|||||||
pub const EX_SPL_MEMO_MAX_SIGNERS: usize = 32;
|
pub const EX_SPL_MEMO_MAX_SIGNERS: usize = 32;
|
||||||
|
|
||||||
/// Exact SPL Memo program generation.
|
/// Exact SPL Memo program generation.
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[serde(rename_all = "snake_case")]
|
#[serde(rename_all = "snake_case")]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/spl/memo/intent/ExSplMemoGeneration.ts"
|
|
||||||
)]
|
|
||||||
pub enum ExSplMemoGeneration {
|
pub enum ExSplMemoGeneration {
|
||||||
/// Historical v1 program, whose runtime ignores supplied accounts.
|
/// Historical v1 program, whose runtime ignores supplied accounts.
|
||||||
V1,
|
V1,
|
||||||
@@ -49,23 +43,15 @@ impl crate::ExSplMemoGeneration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// One ordered signer account supplied to the Memo instruction.
|
/// One ordered signer account supplied to the Memo instruction.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/spl/memo/intent/ExSplMemoSigner.ts"
|
|
||||||
)]
|
|
||||||
pub struct ExSplMemoSigner {
|
pub struct ExSplMemoSigner {
|
||||||
/// Signer public key; duplicates are preserved in instruction order.
|
/// Signer public key; duplicates are preserved in instruction order.
|
||||||
pub pubkey: crate::MdPubkey,
|
pub pubkey: crate::MdPubkey,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Typed SPL Memo operation arguments.
|
/// Typed SPL Memo operation arguments.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[serde(tag = "operation", rename_all = "snake_case")]
|
#[serde(tag = "operation", rename_all = "snake_case")]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/spl/memo/intent/ExSplMemoOperation.ts"
|
|
||||||
)]
|
|
||||||
pub enum ExSplMemoOperation {
|
pub enum ExSplMemoOperation {
|
||||||
/// Add one exact UTF-8 Memo payload with ordered readonly signer accounts.
|
/// Add one exact UTF-8 Memo payload with ordered readonly signer accounts.
|
||||||
AddMemo {
|
AddMemo {
|
||||||
@@ -95,11 +81,7 @@ impl crate::ExSplMemoOperation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Complete typed intent accepted by the SPL Memo executor.
|
/// Complete typed intent accepted by the SPL Memo executor.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/spl/memo/intent/ExSplMemoExecutionIntent.ts"
|
|
||||||
)]
|
|
||||||
pub struct ExSplMemoExecutionIntent {
|
pub struct ExSplMemoExecutionIntent {
|
||||||
/// Stable caller-provided identifier used for logs and replay correlation.
|
/// Stable caller-provided identifier used for logs and replay correlation.
|
||||||
pub intent_id: std::string::String,
|
pub intent_id: std::string::String,
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
// file: ks-lib/src/executor/spl/token/intent.rs
|
// file: ks-lib/src/executor/spl/token/intent.rs
|
||||||
// version: 6
|
// version: 7
|
||||||
|
|
||||||
//! Typed classic SPL Token execution intents.
|
//! Typed classic SPL Token execution intents.
|
||||||
|
|
||||||
use ts_rs::TS; // rust-rules: derive-import
|
|
||||||
|
|
||||||
/// Stable operation code for mint initialization through `InitializeMint2`.
|
/// Stable operation code for mint initialization through `InitializeMint2`.
|
||||||
pub const EX_SPL_TOKEN_INITIALIZE_MINT_OPERATION: &str = "spl.token.initialize_mint";
|
pub const EX_SPL_TOKEN_INITIALIZE_MINT_OPERATION: &str = "spl.token.initialize_mint";
|
||||||
/// Stable operation code for token-account initialization through `InitializeAccount3`.
|
/// Stable operation code for token-account initialization through `InitializeAccount3`.
|
||||||
@@ -85,22 +83,14 @@ pub const EX_SPL_TOKEN_SUPPORTED_OPERATION_CODES: &[&str] = &[
|
|||||||
];
|
];
|
||||||
|
|
||||||
/// Exact unsigned on-chain amount represented as a decimal JSON string.
|
/// Exact unsigned on-chain amount represented as a decimal JSON string.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/spl/token/intent/ExSplClassicTokenAmount.ts"
|
|
||||||
)]
|
|
||||||
pub struct ExSplClassicTokenAmount(
|
pub struct ExSplClassicTokenAmount(
|
||||||
/// Canonical unsigned decimal representation.
|
/// Canonical unsigned decimal representation.
|
||||||
pub std::string::String,
|
pub std::string::String,
|
||||||
);
|
);
|
||||||
|
|
||||||
/// Ordered simple or multisig authority supplied to an instruction builder.
|
/// Ordered simple or multisig authority supplied to an instruction builder.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/spl/token/intent/ExSplClassicTokenAuthority.ts"
|
|
||||||
)]
|
|
||||||
pub struct ExSplClassicTokenAuthority {
|
pub struct ExSplClassicTokenAuthority {
|
||||||
/// Authority account. It signs only when `multisig_signers` is empty.
|
/// Authority account. It signs only when `multisig_signers` is empty.
|
||||||
pub authority: crate::MdPubkey,
|
pub authority: crate::MdPubkey,
|
||||||
@@ -109,12 +99,8 @@ pub struct ExSplClassicTokenAuthority {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Authority domain used by `SetAuthority`.
|
/// Authority domain used by `SetAuthority`.
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[serde(rename_all = "snake_case")]
|
#[serde(rename_all = "snake_case")]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/spl/token/intent/ExSplClassicTokenAuthorityType.ts"
|
|
||||||
)]
|
|
||||||
pub enum ExSplClassicTokenAuthorityType {
|
pub enum ExSplClassicTokenAuthorityType {
|
||||||
/// Mint authority.
|
/// Mint authority.
|
||||||
MintTokens,
|
MintTokens,
|
||||||
@@ -127,12 +113,8 @@ pub enum ExSplClassicTokenAuthorityType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// One officially constructible non-batch instruction.
|
/// One officially constructible non-batch instruction.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[serde(tag = "instruction", rename_all = "snake_case")]
|
#[serde(tag = "instruction", rename_all = "snake_case")]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/spl/token/intent/ExSplClassicTokenSingleOperation.ts"
|
|
||||||
)]
|
|
||||||
pub enum ExSplClassicTokenSingleOperation {
|
pub enum ExSplClassicTokenSingleOperation {
|
||||||
/// Initialize a mint with the current no-Rent builder.
|
/// Initialize a mint with the current no-Rent builder.
|
||||||
InitializeMint {
|
InitializeMint {
|
||||||
@@ -407,12 +389,8 @@ impl crate::ExSplClassicTokenSingleOperation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Top-level SPL Token operation, including the recent bounded Batch builder.
|
/// Top-level SPL Token operation, including the recent bounded Batch builder.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[serde(tag = "operation", rename_all = "snake_case")]
|
#[serde(tag = "operation", rename_all = "snake_case")]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/spl/token/intent/ExSplClassicTokenOperation.ts"
|
|
||||||
)]
|
|
||||||
pub enum ExSplClassicTokenOperation {
|
pub enum ExSplClassicTokenOperation {
|
||||||
/// Build one non-batch instruction.
|
/// Build one non-batch instruction.
|
||||||
Instruction {
|
Instruction {
|
||||||
@@ -446,11 +424,7 @@ impl crate::ExSplClassicTokenOperation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Complete typed intent accepted by the classic SPL Token executor.
|
/// Complete typed intent accepted by the classic SPL Token executor.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/spl/token/intent/ExSplClassicTokenExecutionIntent.ts"
|
|
||||||
)]
|
|
||||||
pub struct ExSplClassicTokenExecutionIntent {
|
pub struct ExSplClassicTokenExecutionIntent {
|
||||||
/// Stable caller-provided identifier used for logs and replay correlation.
|
/// Stable caller-provided identifier used for logs and replay correlation.
|
||||||
pub intent_id: std::string::String,
|
pub intent_id: std::string::String,
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
// file: ks-lib/src/executor/spl/token_2022/confidential.rs
|
// file: ks-lib/src/executor/spl/token_2022/confidential.rs
|
||||||
// version: 10
|
// version: 11
|
||||||
|
|
||||||
//! Audited Confidential Transfer execution contracts.
|
//! Audited Confidential Transfer execution contracts.
|
||||||
|
|
||||||
use ts_rs::TS; // rust-rules: derive-import
|
|
||||||
|
|
||||||
/// Maximum number of proof references accepted by one confidential operation.
|
/// Maximum number of proof references accepted by one confidential operation.
|
||||||
pub const EX_SPL_TOKEN_2022_MAX_CONFIDENTIAL_PROOF_REFERENCES: usize = 5;
|
pub const EX_SPL_TOKEN_2022_MAX_CONFIDENTIAL_PROOF_REFERENCES: usize = 5;
|
||||||
/// Exact byte length of an ElGamal public key accepted from callers.
|
/// Exact byte length of an ElGamal public key accepted from callers.
|
||||||
@@ -27,11 +25,7 @@ pub const EX_SPL_TOKEN_2022_CONFIDENTIAL_TRANSFER_WITH_FEE_INSTRUCTION_DATA_BYTE
|
|||||||
2 + EX_SPL_TOKEN_2022_CONFIDENTIAL_TRANSFER_WITH_FEE_PAYLOAD_BYTES;
|
2 + EX_SPL_TOKEN_2022_CONFIDENTIAL_TRANSFER_WITH_FEE_PAYLOAD_BYTES;
|
||||||
|
|
||||||
/// Caller-generated ElGamal public key encoded as lowercase or uppercase hexadecimal.
|
/// Caller-generated ElGamal public key encoded as lowercase or uppercase hexadecimal.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/spl/token_2022/confidential/ExSplTokenElGamalPubkey.ts"
|
|
||||||
)]
|
|
||||||
pub struct ExSplTokenElGamalPubkey(pub std::string::String);
|
pub struct ExSplTokenElGamalPubkey(pub std::string::String);
|
||||||
|
|
||||||
impl ExSplTokenElGamalPubkey {
|
impl ExSplTokenElGamalPubkey {
|
||||||
@@ -56,11 +50,7 @@ impl ExSplTokenElGamalPubkey {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Caller-generated decryptable balance encoded as hexadecimal bytes.
|
/// Caller-generated decryptable balance encoded as hexadecimal bytes.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/spl/token_2022/confidential/ExSplTokenDecryptableBalance.ts"
|
|
||||||
)]
|
|
||||||
pub struct ExSplTokenDecryptableBalance(pub std::string::String);
|
pub struct ExSplTokenDecryptableBalance(pub std::string::String);
|
||||||
|
|
||||||
impl ExSplTokenDecryptableBalance {
|
impl ExSplTokenDecryptableBalance {
|
||||||
@@ -86,11 +76,7 @@ impl ExSplTokenDecryptableBalance {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Caller-generated ElGamal ciphertext encoded as hexadecimal bytes.
|
/// Caller-generated ElGamal ciphertext encoded as hexadecimal bytes.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/spl/token_2022/confidential/ExSplTokenElGamalCiphertext.ts"
|
|
||||||
)]
|
|
||||||
pub struct ExSplTokenElGamalCiphertext(pub std::string::String);
|
pub struct ExSplTokenElGamalCiphertext(pub std::string::String);
|
||||||
|
|
||||||
impl ExSplTokenElGamalCiphertext {
|
impl ExSplTokenElGamalCiphertext {
|
||||||
@@ -153,12 +139,8 @@ fn decode_hex_nibble(value: u8) -> Option<u8> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Proof statement required by a Confidential Transfer operation.
|
/// Proof statement required by a Confidential Transfer operation.
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[serde(rename_all = "snake_case")]
|
#[serde(rename_all = "snake_case")]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/spl/token_2022/confidential/ExSplTokenConfidentialProofKind.ts"
|
|
||||||
)]
|
|
||||||
pub enum ExSplTokenConfidentialProofKind {
|
pub enum ExSplTokenConfidentialProofKind {
|
||||||
/// ElGamal public-key validity.
|
/// ElGamal public-key validity.
|
||||||
PubkeyValidity,
|
PubkeyValidity,
|
||||||
@@ -183,12 +165,8 @@ pub enum ExSplTokenConfidentialProofKind {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Explicit source for one already-generated zero-knowledge proof statement.
|
/// Explicit source for one already-generated zero-knowledge proof statement.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[serde(rename_all = "snake_case", tag = "mode")]
|
#[serde(rename_all = "snake_case", tag = "mode")]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/spl/token_2022/confidential/ExSplTokenConfidentialProofLocation.ts"
|
|
||||||
)]
|
|
||||||
pub enum ExSplTokenConfidentialProofLocation {
|
pub enum ExSplTokenConfidentialProofLocation {
|
||||||
/// Relative transaction offset of a separate ZK proof-program instruction.
|
/// Relative transaction offset of a separate ZK proof-program instruction.
|
||||||
InstructionOffset {
|
InstructionOffset {
|
||||||
@@ -216,12 +194,8 @@ impl ExSplTokenConfidentialProofLocation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// One proof requirement paired with its explicit location.
|
/// One proof requirement paired with its explicit location.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/spl/token_2022/confidential/ExSplTokenConfidentialProofReference.ts"
|
|
||||||
)]
|
|
||||||
pub struct ExSplTokenConfidentialProofReference {
|
pub struct ExSplTokenConfidentialProofReference {
|
||||||
/// Exact proof statement required by the Token-2022 builder.
|
/// Exact proof statement required by the Token-2022 builder.
|
||||||
pub kind: ExSplTokenConfidentialProofKind,
|
pub kind: ExSplTokenConfidentialProofKind,
|
||||||
@@ -230,12 +204,8 @@ pub struct ExSplTokenConfidentialProofReference {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Audited Confidential Transfer operation surface.
|
/// Audited Confidential Transfer operation surface.
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[serde(rename_all = "snake_case")]
|
#[serde(rename_all = "snake_case")]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/spl/token_2022/confidential/ExSplTokenConfidentialOperation.ts"
|
|
||||||
)]
|
|
||||||
pub enum ExSplTokenConfidentialOperation {
|
pub enum ExSplTokenConfidentialOperation {
|
||||||
/// Initialize confidential-transfer mint configuration.
|
/// Initialize confidential-transfer mint configuration.
|
||||||
InitializeMint,
|
InitializeMint,
|
||||||
@@ -332,12 +302,8 @@ impl ExSplTokenConfidentialOperation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Audited Confidential Mint/Burn operation surface.
|
/// Audited Confidential Mint/Burn operation surface.
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[serde(rename_all = "snake_case")]
|
#[serde(rename_all = "snake_case")]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/spl/token_2022/confidential/ExSplTokenConfidentialMintBurnOperation.ts"
|
|
||||||
)]
|
|
||||||
pub enum ExSplTokenConfidentialMintBurnOperation {
|
pub enum ExSplTokenConfidentialMintBurnOperation {
|
||||||
/// Initialize the mint extension with supply encryption material.
|
/// Initialize the mint extension with supply encryption material.
|
||||||
InitializeMint,
|
InitializeMint,
|
||||||
@@ -395,12 +361,8 @@ impl ExSplTokenConfidentialMintBurnOperation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Executor-readiness classification established by the Confidential Transfer audit.
|
/// Executor-readiness classification established by the Confidential Transfer audit.
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[serde(rename_all = "snake_case")]
|
#[serde(rename_all = "snake_case")]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/spl/token_2022/confidential/ExSplTokenConfidentialExecutorSupport.ts"
|
|
||||||
)]
|
|
||||||
pub enum ExSplTokenConfidentialExecutorSupport {
|
pub enum ExSplTokenConfidentialExecutorSupport {
|
||||||
/// The builder needs only public fields and ordinary authorities.
|
/// The builder needs only public fields and ordinary authorities.
|
||||||
PublicBuilderReady,
|
PublicBuilderReady,
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
// file: ks-lib/src/executor/spl/token_2022/intent.rs
|
// file: ks-lib/src/executor/spl/token_2022/intent.rs
|
||||||
// version: 28
|
// version: 29
|
||||||
|
|
||||||
//! Typed Token-2022 execution intents.
|
//! Typed Token-2022 execution intents.
|
||||||
|
|
||||||
use ts_rs::TS; // rust-rules: derive-import
|
|
||||||
|
|
||||||
/// Stable operation code for mint initialization through `InitializeMint2`.
|
/// Stable operation code for mint initialization through `InitializeMint2`.
|
||||||
pub const EX_SPL_TOKEN_2022_INITIALIZE_MINT_OPERATION: &str = "spl.token_2022.initialize_mint";
|
pub const EX_SPL_TOKEN_2022_INITIALIZE_MINT_OPERATION: &str = "spl.token_2022.initialize_mint";
|
||||||
/// Stable operation code for token-account initialization through `InitializeAccount3`.
|
/// Stable operation code for token-account initialization through `InitializeAccount3`.
|
||||||
@@ -357,33 +355,21 @@ pub const EX_SPL_TOKEN_2022_SUPPORTED_OPERATION_CODES: &[&str] = &[
|
|||||||
];
|
];
|
||||||
|
|
||||||
/// Exact unsigned on-chain amount represented as a decimal JSON string.
|
/// Exact unsigned on-chain amount represented as a decimal JSON string.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/spl/token_2022/intent/ExSplTokenAmount.ts"
|
|
||||||
)]
|
|
||||||
pub struct ExSplTokenAmount(
|
pub struct ExSplTokenAmount(
|
||||||
/// Canonical unsigned decimal representation.
|
/// Canonical unsigned decimal representation.
|
||||||
pub std::string::String,
|
pub std::string::String,
|
||||||
);
|
);
|
||||||
|
|
||||||
/// Positive normal finite scaled-UI multiplier represented as a decimal JSON string.
|
/// Positive normal finite scaled-UI multiplier represented as a decimal JSON string.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/spl/token_2022/intent/ExSplTokenMultiplier.ts"
|
|
||||||
)]
|
|
||||||
pub struct ExSplTokenMultiplier(
|
pub struct ExSplTokenMultiplier(
|
||||||
/// Decimal representation parsed to the official `f64` wire contract.
|
/// Decimal representation parsed to the official `f64` wire contract.
|
||||||
pub std::string::String,
|
pub std::string::String,
|
||||||
);
|
);
|
||||||
|
|
||||||
/// Ordered simple or multisig authority supplied to an instruction builder.
|
/// Ordered simple or multisig authority supplied to an instruction builder.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/spl/token_2022/intent/ExSplTokenAuthority.ts"
|
|
||||||
)]
|
|
||||||
pub struct ExSplTokenAuthority {
|
pub struct ExSplTokenAuthority {
|
||||||
/// Authority account. It signs only when `multisig_signers` is empty.
|
/// Authority account. It signs only when `multisig_signers` is empty.
|
||||||
pub authority: crate::MdPubkey,
|
pub authority: crate::MdPubkey,
|
||||||
@@ -392,12 +378,8 @@ pub struct ExSplTokenAuthority {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Authority domain used by `SetAuthority`.
|
/// Authority domain used by `SetAuthority`.
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[serde(rename_all = "snake_case")]
|
#[serde(rename_all = "snake_case")]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/spl/token_2022/intent/ExSplTokenAuthorityType.ts"
|
|
||||||
)]
|
|
||||||
pub enum ExSplTokenAuthorityType {
|
pub enum ExSplTokenAuthorityType {
|
||||||
/// Mint authority.
|
/// Mint authority.
|
||||||
MintTokens,
|
MintTokens,
|
||||||
@@ -410,12 +392,8 @@ pub enum ExSplTokenAuthorityType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Default state assigned to newly initialized Token-2022 accounts.
|
/// Default state assigned to newly initialized Token-2022 accounts.
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[serde(rename_all = "snake_case")]
|
#[serde(rename_all = "snake_case")]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/spl/token_2022/intent/ExSplTokenDefaultAccountState.ts"
|
|
||||||
)]
|
|
||||||
pub enum ExSplTokenDefaultAccountState {
|
pub enum ExSplTokenDefaultAccountState {
|
||||||
/// Newly initialized accounts remain usable.
|
/// Newly initialized accounts remain usable.
|
||||||
Initialized,
|
Initialized,
|
||||||
@@ -424,12 +402,8 @@ pub enum ExSplTokenDefaultAccountState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Token-metadata field selected for an update.
|
/// Token-metadata field selected for an update.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[serde(rename_all = "snake_case", tag = "kind", content = "key")]
|
#[serde(rename_all = "snake_case", tag = "kind", content = "key")]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/spl/token_2022/intent/ExSplTokenMetadataField.ts"
|
|
||||||
)]
|
|
||||||
pub enum ExSplTokenMetadataField {
|
pub enum ExSplTokenMetadataField {
|
||||||
/// Update the required name field.
|
/// Update the required name field.
|
||||||
Name,
|
Name,
|
||||||
@@ -442,12 +416,8 @@ pub enum ExSplTokenMetadataField {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// One officially constructible non-batch instruction.
|
/// One officially constructible non-batch instruction.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[serde(tag = "instruction", rename_all = "snake_case")]
|
#[serde(tag = "instruction", rename_all = "snake_case")]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/spl/token_2022/intent/ExSplTokenSingleOperation.ts"
|
|
||||||
)]
|
|
||||||
pub enum ExSplTokenSingleOperation {
|
pub enum ExSplTokenSingleOperation {
|
||||||
/// Initialize a mint with the current no-Rent builder.
|
/// Initialize a mint with the current no-Rent builder.
|
||||||
InitializeMint {
|
InitializeMint {
|
||||||
@@ -1605,12 +1575,8 @@ impl crate::ExSplTokenSingleOperation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Top-level SPL Token operation, including the recent bounded Batch builder.
|
/// Top-level SPL Token operation, including the recent bounded Batch builder.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[serde(tag = "operation", rename_all = "snake_case")]
|
#[serde(tag = "operation", rename_all = "snake_case")]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/spl/token_2022/intent/ExSplToken2022Operation.ts"
|
|
||||||
)]
|
|
||||||
pub enum ExSplToken2022Operation {
|
pub enum ExSplToken2022Operation {
|
||||||
/// Build one non-batch instruction.
|
/// Build one non-batch instruction.
|
||||||
Instruction {
|
Instruction {
|
||||||
@@ -1644,11 +1610,7 @@ impl crate::ExSplToken2022Operation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Complete typed intent accepted by the Token-2022 executor.
|
/// Complete typed intent accepted by the Token-2022 executor.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/executor/spl/token_2022/intent/ExSplToken2022ExecutionIntent.ts"
|
|
||||||
)]
|
|
||||||
pub struct ExSplToken2022ExecutionIntent {
|
pub struct ExSplToken2022ExecutionIntent {
|
||||||
/// Stable caller-provided identifier used for logs and replay correlation.
|
/// Stable caller-provided identifier used for logs and replay correlation.
|
||||||
pub intent_id: std::string::String,
|
pub intent_id: std::string::String,
|
||||||
|
|||||||
@@ -1,16 +1,10 @@
|
|||||||
// file: ks-lib/src/model/decoded.rs
|
// file: ks-lib/src/model/decoded.rs
|
||||||
// version: 6
|
// version: 7
|
||||||
|
|
||||||
//! Shared decoded protocol event model.
|
//! Shared decoded protocol event model.
|
||||||
|
|
||||||
use ts_rs::TS; // rust-rules: derive-import
|
|
||||||
|
|
||||||
/// Source from which a decoded event was derived.
|
/// Source from which a decoded event was derived.
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/model/decoded/EventSourceKind.ts"
|
|
||||||
)]
|
|
||||||
pub enum MdEventSourceKind {
|
pub enum MdEventSourceKind {
|
||||||
/// Top-level instruction.
|
/// Top-level instruction.
|
||||||
Instruction,
|
Instruction,
|
||||||
@@ -33,11 +27,7 @@ pub enum MdEventSourceKind {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Confidence level for a decoded event.
|
/// Confidence level for a decoded event.
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/model/decoded/DecoderConfidence.ts"
|
|
||||||
)]
|
|
||||||
pub enum MdDecoderConfidence {
|
pub enum MdDecoderConfidence {
|
||||||
/// Exact manual decode.
|
/// Exact manual decode.
|
||||||
Exact,
|
Exact,
|
||||||
@@ -56,11 +46,7 @@ pub enum MdDecoderConfidence {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Protocol-level decoded event produced by a decoder.
|
/// Protocol-level decoded event produced by a decoder.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/model/decoded/DecodedProtocolEvent.ts"
|
|
||||||
)]
|
|
||||||
pub struct MdDecodedProtocolEvent {
|
pub struct MdDecodedProtocolEvent {
|
||||||
/// Transaction signature.
|
/// Transaction signature.
|
||||||
pub signature: crate::MdSignature,
|
pub signature: crate::MdSignature,
|
||||||
|
|||||||
@@ -1,16 +1,10 @@
|
|||||||
// file: ks-lib/src/model/materialized.rs
|
// file: ks-lib/src/model/materialized.rs
|
||||||
// version: 7
|
// version: 8
|
||||||
|
|
||||||
//! Shared materialized business event model.
|
//! Shared materialized business event model.
|
||||||
|
|
||||||
use ts_rs::TS; // rust-rules: derive-import
|
|
||||||
|
|
||||||
/// Materialized event family.
|
/// Materialized event family.
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/model/materialized/MaterializedEventFamily.ts"
|
|
||||||
)]
|
|
||||||
pub enum MdMaterializedEventFamily {
|
pub enum MdMaterializedEventFamily {
|
||||||
/// Trade materialization.
|
/// Trade materialization.
|
||||||
Trade,
|
Trade,
|
||||||
@@ -63,11 +57,7 @@ pub enum MdMaterializedEventFamily {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Business-level materialized event placeholder.
|
/// Business-level materialized event placeholder.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/model/materialized/MaterializedEvent.ts"
|
|
||||||
)]
|
|
||||||
pub struct MdMaterializedEvent {
|
pub struct MdMaterializedEvent {
|
||||||
/// Source transaction signature.
|
/// Source transaction signature.
|
||||||
pub signature: crate::MdSignature,
|
pub signature: crate::MdSignature,
|
||||||
|
|||||||
@@ -1,56 +1,30 @@
|
|||||||
// file: ks-lib/src/model/nomenclature.rs
|
// file: ks-lib/src/model/nomenclature.rs
|
||||||
// version: 6
|
// version: 7
|
||||||
|
|
||||||
//! Shared protocol, surface, and event nomenclature types.
|
//! Shared protocol, surface, and event nomenclature types.
|
||||||
|
|
||||||
use ts_rs::TS; // rust-rules: derive-import
|
|
||||||
|
|
||||||
/// Stable internal program code.
|
/// Stable internal program code.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, Hash, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Debug, Eq, PartialEq, Hash, serde::Deserialize, serde::Serialize)]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/model/nomenclature/ProgramCode.ts"
|
|
||||||
)]
|
|
||||||
pub struct MdProgramCode(pub std::string::String);
|
pub struct MdProgramCode(pub std::string::String);
|
||||||
|
|
||||||
/// Protocol family code, for example `raydium` or `meteora`.
|
/// Protocol family code, for example `raydium` or `meteora`.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, Hash, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Debug, Eq, PartialEq, Hash, serde::Deserialize, serde::Serialize)]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/model/nomenclature/ProtocolCode.ts"
|
|
||||||
)]
|
|
||||||
pub struct MdProtocolCode(pub std::string::String);
|
pub struct MdProtocolCode(pub std::string::String);
|
||||||
|
|
||||||
/// Concrete protocol surface code, for example `raydium_amm_v4`.
|
/// Concrete protocol surface code, for example `raydium_amm_v4`.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, Hash, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Debug, Eq, PartialEq, Hash, serde::Deserialize, serde::Serialize)]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/model/nomenclature/SurfaceCode.ts"
|
|
||||||
)]
|
|
||||||
pub struct MdSurfaceCode(pub std::string::String);
|
pub struct MdSurfaceCode(pub std::string::String);
|
||||||
|
|
||||||
/// Event name without surface prefix.
|
/// Event name without surface prefix.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, Hash, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Debug, Eq, PartialEq, Hash, serde::Deserialize, serde::Serialize)]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/model/nomenclature/EventName.ts"
|
|
||||||
)]
|
|
||||||
pub struct MdEventName(pub std::string::String);
|
pub struct MdEventName(pub std::string::String);
|
||||||
|
|
||||||
/// Canonical event code in `<surface_code>.<event_name>` format.
|
/// Canonical event code in `<surface_code>.<event_name>` format.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, Hash, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Debug, Eq, PartialEq, Hash, serde::Deserialize, serde::Serialize)]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/model/nomenclature/EventCode.ts"
|
|
||||||
)]
|
|
||||||
pub struct MdEventCode(pub std::string::String);
|
pub struct MdEventCode(pub std::string::String);
|
||||||
|
|
||||||
/// High-level event family.
|
/// High-level event family.
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, serde::Deserialize, serde::Serialize)]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/model/nomenclature/EventFamily.ts"
|
|
||||||
)]
|
|
||||||
pub enum MdEventFamily {
|
pub enum MdEventFamily {
|
||||||
/// Swap or buy/sell event.
|
/// Swap or buy/sell event.
|
||||||
Trade,
|
Trade,
|
||||||
|
|||||||
@@ -1,16 +1,10 @@
|
|||||||
// file: ks-lib/src/model/observation.rs
|
// file: ks-lib/src/model/observation.rs
|
||||||
// version: 6
|
// version: 7
|
||||||
|
|
||||||
//! Shared program observation model.
|
//! Shared program observation model.
|
||||||
|
|
||||||
use ts_rs::TS; // rust-rules: derive-import
|
|
||||||
|
|
||||||
/// Generic program observation derived from a Solana instruction.
|
/// Generic program observation derived from a Solana instruction.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/model/observation/ProgramObservation.ts"
|
|
||||||
)]
|
|
||||||
pub struct MdProgramObservation {
|
pub struct MdProgramObservation {
|
||||||
/// Transaction signature.
|
/// Transaction signature.
|
||||||
pub signature: crate::MdSignature,
|
pub signature: crate::MdSignature,
|
||||||
|
|||||||
@@ -1,46 +1,26 @@
|
|||||||
// file: ks-lib/src/model/solana.rs
|
// file: ks-lib/src/model/solana.rs
|
||||||
// version: 6
|
// version: 7
|
||||||
|
|
||||||
//! Shared Solana primitive wrapper types.
|
//! Shared Solana primitive wrapper types.
|
||||||
|
|
||||||
use ts_rs::TS; // rust-rules: derive-import
|
|
||||||
|
|
||||||
/// Solana transaction signature.
|
/// Solana transaction signature.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, Hash, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Debug, Eq, PartialEq, Hash, serde::Deserialize, serde::Serialize)]
|
||||||
#[ts(export, export_to = "../frontend/ts/bindings/ks_lib/model/solana/MdSignature.ts")]
|
|
||||||
pub struct MdSignature(pub std::string::String);
|
pub struct MdSignature(pub std::string::String);
|
||||||
|
|
||||||
/// Solana slot.
|
/// Solana slot.
|
||||||
#[derive(
|
#[derive(
|
||||||
Clone,
|
Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, serde::Deserialize, serde::Serialize,
|
||||||
Copy,
|
|
||||||
Debug,
|
|
||||||
Eq,
|
|
||||||
PartialEq,
|
|
||||||
Ord,
|
|
||||||
PartialOrd,
|
|
||||||
Hash,
|
|
||||||
serde::Deserialize,
|
|
||||||
serde::Serialize,
|
|
||||||
TS,
|
|
||||||
)]
|
)]
|
||||||
#[ts(export, export_to = "../frontend/ts/bindings/ks_lib/model/solana/MdSlot.ts")]
|
|
||||||
pub struct MdSlot(pub u64);
|
pub struct MdSlot(pub u64);
|
||||||
|
|
||||||
/// Solana program id.
|
/// Solana program id.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, Hash, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Debug, Eq, PartialEq, Hash, serde::Deserialize, serde::Serialize)]
|
||||||
#[ts(export, export_to = "../frontend/ts/bindings/ks_lib/model/solana/MdProgramId.ts")]
|
|
||||||
pub struct MdProgramId(pub std::string::String);
|
pub struct MdProgramId(pub std::string::String);
|
||||||
|
|
||||||
/// Solana public key.
|
/// Solana public key.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, Hash, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Debug, Eq, PartialEq, Hash, serde::Deserialize, serde::Serialize)]
|
||||||
#[ts(export, export_to = "../frontend/ts/bindings/ks_lib/model/solana/MdPubkey.ts")]
|
|
||||||
pub struct MdPubkey(pub std::string::String);
|
pub struct MdPubkey(pub std::string::String);
|
||||||
|
|
||||||
/// Stable top-level or inner instruction path.
|
/// Stable top-level or inner instruction path.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, Hash, serde::Deserialize, serde::Serialize, TS)]
|
#[derive(Clone, Debug, Eq, PartialEq, Hash, serde::Deserialize, serde::Serialize)]
|
||||||
#[ts(
|
|
||||||
export,
|
|
||||||
export_to = "../frontend/ts/bindings/ks_lib/model/solana/MdInstructionPath.ts"
|
|
||||||
)]
|
|
||||||
pub struct MdInstructionPath(pub std::string::String);
|
pub struct MdInstructionPath(pub std::string::String);
|
||||||
|
|||||||
@@ -1,8 +1,14 @@
|
|||||||
<!-- file: ks-logging/CHANGELOG.md -->
|
<!-- file: ks-logging/CHANGELOG.md -->
|
||||||
<!-- version: 18 -->
|
<!-- version: 20 -->
|
||||||
|
|
||||||
# CHANGELOG — ks-logging
|
# CHANGELOG — ks-logging
|
||||||
|
|
||||||
|
## `0.5.1-pre.008`
|
||||||
|
|
||||||
|
- Fix: remplace un ancien fragment de credential Helius utilisé comme canari négatif par le nom synthétique `KS_SECRET_HELIUS_API_KEY`; aucune donnée réelle ou partielle de credential ne doit être conservée dans les tests.
|
||||||
|
|
||||||
|
- clarifie que la non-divulgation des secrets de configuration est garantie à la source et aux frontières public/diagnostic ; conserve comme défense en profondeur future l'évaluation d'un redactor générique pour des chaînes arbitraires fournies par les appelants.
|
||||||
|
|
||||||
## `0.5.1-pre.007`
|
## `0.5.1-pre.007`
|
||||||
|
|
||||||
- place `logs_directory` hors profils dans le document logging et le rend configurable via `${KS_LOGS_DIRECTORY:-logs}` ;
|
- place `logs_directory` hors profils dans le document logging et le rend configurable via `${KS_LOGS_DIRECTORY:-logs}` ;
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
<!-- file: ks-logging/TODO.md -->
|
<!-- file: ks-logging/TODO.md -->
|
||||||
<!-- version: 6 -->
|
<!-- version: 7 -->
|
||||||
|
|
||||||
# TODO — ks-logging
|
# TODO — ks-logging
|
||||||
|
|
||||||
## Série `0.5.x`
|
## Série `0.5.x`
|
||||||
|
|
||||||
- [ ] `0.5.1` - intégrer la propagation de sensibilité et le camouflage des valeurs provenant de `KS_SECRET_*` / `KB_SECRET_*` avant tout diagnostic ou log.
|
|
||||||
- [ ] Compatibilité - préserver targets, niveaux, filtres, formats, routes et sémantique wildcard pendant les prochaines migrations.
|
- [ ] Compatibilité - préserver targets, niveaux, filtres, formats, routes et sémantique wildcard pendant les prochaines migrations.
|
||||||
- [ ] Contrat - réévaluer `LogFileRoute`, actuellement sans consommateur actif hors de la crate.
|
- [ ] Contrat - réévaluer `LogFileRoute`, actuellement sans consommateur actif hors de la crate.
|
||||||
- [ ] Tests - ajouter les canaris garantissant qu’un secret résolu n’atteint jamais une sortie logging.
|
- [ ] Défense en profondeur - évaluer ultérieurement un filtre de sortie générique pour les secrets fournis arbitrairement par les appelants, sans remplacer l’interdiction de journaliser ces valeurs à la source.
|
||||||
- [ ] Documentation - maintenir le schéma et les exemples logging alignés avec les types possédés par la crate.
|
- [ ] Documentation - maintenir le schéma et les exemples logging alignés avec les types possédés par la crate.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// file: ks-logging/src/document.rs
|
// file: ks-logging/src/document.rs
|
||||||
// version: 5
|
// version: 6
|
||||||
|
|
||||||
//! Independent logging configuration document loading and validation.
|
//! Independent logging configuration document loading and validation.
|
||||||
|
|
||||||
@@ -351,7 +351,8 @@ fn require_non_empty(value: &str, field_name: &str) -> ks_core::Result<()> {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
const DEFAULT_LOGGING_CONFIG: &str = include_str!("../../config/logging.config.json");
|
const DEFAULT_LOGGING_CONFIG: &str = include_str!("../../config/logging.config.json");
|
||||||
const EXAMPLE_LOGGING_CONFIG: &str = include_str!("../../config/example.logging.config.json");
|
const EXAMPLE_LOGGING_CONFIG: &str =
|
||||||
|
include_str!("../../config/exemples/example.logging.config.json");
|
||||||
|
|
||||||
fn parse_default_value() -> serde_json::Value {
|
fn parse_default_value() -> serde_json::Value {
|
||||||
let result = serde_json::from_str::<serde_json::Value>(DEFAULT_LOGGING_CONFIG);
|
let result = serde_json::from_str::<serde_json::Value>(DEFAULT_LOGGING_CONFIG);
|
||||||
@@ -522,7 +523,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn default_logging_config_uses_canonical_wallet_and_pipeline_routes() {
|
fn default_logging_config_uses_canonical_wallet_and_pipeline_routes() {
|
||||||
assert!(!DEFAULT_LOGGING_CONFIG.contains("api-key=95e73621"));
|
assert!(!DEFAULT_LOGGING_CONFIG.contains("KS_SECRET_HELIUS_API_KEY"));
|
||||||
assert!(!DEFAULT_LOGGING_CONFIG.contains("\"ks_wallet\""));
|
assert!(!DEFAULT_LOGGING_CONFIG.contains("\"ks_wallet\""));
|
||||||
assert!(DEFAULT_LOGGING_CONFIG.contains("\"ks-wallet\""));
|
assert!(DEFAULT_LOGGING_CONFIG.contains("\"ks-wallet\""));
|
||||||
assert!(DEFAULT_LOGGING_CONFIG.contains("\"ks-pipeline\""));
|
assert!(DEFAULT_LOGGING_CONFIG.contains("\"ks-pipeline\""));
|
||||||
|
|||||||
@@ -1,8 +1,15 @@
|
|||||||
<!-- file: ks-onchain-transport/CHANGELOG.md -->
|
<!-- file: ks-onchain-transport/CHANGELOG.md -->
|
||||||
<!-- version: 15 -->
|
<!-- version: 21 -->
|
||||||
|
|
||||||
# CHANGELOG — ks-onchain-transport
|
# CHANGELOG — ks-onchain-transport
|
||||||
|
|
||||||
|
## `0.5.1-pre.008`
|
||||||
|
|
||||||
|
- Fix: retire complètement les URLs résolues des snapshots HTTP/WS/session, conserve ces snapshots backend-only et non sérialisables directement, sanitise le `Debug` de `WsSession`/`RpcEndpoint`, et ne recopie plus les erreurs brutes de connexion HTTP/WS susceptibles d’inclure une URL résolue. Les corps HTTP non-success et messages JSON-RPC distants ne sont plus recopiés dans les erreurs/logs afin qu’un fournisseur ne puisse pas y réinjecter une URL ou un credential. Le getter d’URL HTTP inutilisé est supprimé et le getter WS nécessaire à la session devient `pub(crate)`.
|
||||||
|
|
||||||
|
- remplace les dérivations `Debug` de `HttpClient` et `WsClient` par des implémentations manuelles sanitisées qui ne recopient aucune chaîne issue de la configuration d’endpoint et utilisent un marqueur `<redacted>` ;
|
||||||
|
- conserve ainsi `Debug` sur les clients et pools sans réintroduire `Debug` sur `ks_config::HttpEndpointConfig` / `WsEndpointConfig`, et ajoute des tests canaris HTTP/WS de non-divulgation.
|
||||||
|
|
||||||
## `0.5.1-pre.007`
|
## `0.5.1-pre.007`
|
||||||
|
|
||||||
- aligne les fixtures d’exécution sur le déplacement des autorisations `*_send_enabled` vers `ExecutionConfig` ; le comportement RPC reste inchangé.
|
- aligne les fixtures d’exécution sur le déplacement des autorisations `*_send_enabled` vers `ExecutionConfig` ; le comportement RPC reste inchangé.
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
// file: ks-onchain-transport/src/client.rs
|
// file: ks-onchain-transport/src/client.rs
|
||||||
// version: 4
|
// version: 5
|
||||||
|
|
||||||
//! RPC client scaffold for Solana ingestion.
|
//! RPC client scaffold for Solana ingestion.
|
||||||
|
|
||||||
/// RPC endpoint configuration.
|
/// RPC endpoint configuration.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Eq, PartialEq)]
|
||||||
pub struct RpcEndpoint {
|
pub struct RpcEndpoint {
|
||||||
/// HTTP RPC URL.
|
/// HTTP RPC URL.
|
||||||
pub http_url: std::string::String,
|
pub http_url: std::string::String,
|
||||||
@@ -12,6 +12,17 @@ pub struct RpcEndpoint {
|
|||||||
pub ws_url: std::option::Option<std::string::String>,
|
pub ws_url: std::option::Option<std::string::String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Debug for crate::RpcEndpoint {
|
||||||
|
fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
let ws_state = if self.ws_url.is_some() { "configured" } else { "missing" };
|
||||||
|
return formatter
|
||||||
|
.debug_struct("RpcEndpoint")
|
||||||
|
.field("http_url", &"<redacted>")
|
||||||
|
.field("ws_url", &ws_state)
|
||||||
|
.finish();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Minimal Solana RPC client abstraction.
|
/// Minimal Solana RPC client abstraction.
|
||||||
pub trait SolanaRpcClient {
|
pub trait SolanaRpcClient {
|
||||||
/// Fetches a raw transaction payload by signature.
|
/// Fetches a raw transaction payload by signature.
|
||||||
@@ -20,3 +31,22 @@ pub trait SolanaRpcClient {
|
|||||||
signature: &ks_lib::MdSignature,
|
signature: &ks_lib::MdSignature,
|
||||||
) -> ks_core::Result<std::option::Option<std::string::String>>;
|
) -> ks_core::Result<std::option::Option<std::string::String>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
#[test]
|
||||||
|
fn rpc_endpoint_debug_omits_resolved_urls() {
|
||||||
|
let endpoint = crate::RpcEndpoint {
|
||||||
|
http_url: "https://HTTP-RPC-SECRET-CANARY.invalid/?api-key=secret".to_string(),
|
||||||
|
ws_url: std::option::Option::Some(
|
||||||
|
"wss://WS-RPC-SECRET-CANARY.invalid/?api-key=secret".to_string(),
|
||||||
|
),
|
||||||
|
};
|
||||||
|
let rendered = format!("{endpoint:?}");
|
||||||
|
assert!(rendered.contains("<redacted>"));
|
||||||
|
assert!(rendered.contains("configured"));
|
||||||
|
assert!(!rendered.contains("HTTP-RPC-SECRET-CANARY"));
|
||||||
|
assert!(!rendered.contains("WS-RPC-SECRET-CANARY"));
|
||||||
|
assert!(!rendered.contains("api-key=secret"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// file: ks-onchain-transport/src/http_client.rs
|
// file: ks-onchain-transport/src/http_client.rs
|
||||||
// version: 14
|
// version: 20
|
||||||
|
|
||||||
//! HTTP JSON-RPC client for standard Solana RPC endpoints.
|
//! HTTP JSON-RPC client for standard Solana RPC endpoints.
|
||||||
|
|
||||||
@@ -15,21 +15,30 @@ pub enum HttpMethodClass {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Snapshot of one pooled HTTP endpoint.
|
/// Snapshot of one pooled HTTP endpoint.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize)]
|
#[derive(Clone, Eq, PartialEq)]
|
||||||
#[serde(rename_all = "camelCase")]
|
|
||||||
pub struct HttpPoolClientSnapshot {
|
pub struct HttpPoolClientSnapshot {
|
||||||
/// Logical endpoint name.
|
/// Logical endpoint name.
|
||||||
pub endpoint_name: std::string::String,
|
pub endpoint_name: std::string::String,
|
||||||
/// Provider name.
|
/// Provider name.
|
||||||
pub provider: std::string::String,
|
pub provider: std::string::String,
|
||||||
/// Endpoint URL.
|
|
||||||
pub endpoint_url: std::string::String,
|
|
||||||
/// Supported roles.
|
/// Supported roles.
|
||||||
pub roles: std::vec::Vec<crate::EndpointRoleSnapshot>,
|
pub roles: std::vec::Vec<crate::EndpointRoleSnapshot>,
|
||||||
/// Status string.
|
/// Status string.
|
||||||
pub status: std::string::String,
|
pub status: std::string::String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Debug for crate::HttpPoolClientSnapshot {
|
||||||
|
fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
return formatter
|
||||||
|
.debug_struct("HttpPoolClientSnapshot")
|
||||||
|
.field("endpoint_name", &self.endpoint_name)
|
||||||
|
.field("provider", &self.provider)
|
||||||
|
.field("roles", &self.roles)
|
||||||
|
.field("status", &self.status)
|
||||||
|
.finish();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct HttpRequestLimitState {
|
struct HttpRequestLimitState {
|
||||||
available_tokens: f64,
|
available_tokens: f64,
|
||||||
@@ -138,7 +147,7 @@ impl HttpRequestLimiter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// HTTP JSON-RPC client bound to one configured endpoint.
|
/// HTTP JSON-RPC client bound to one configured endpoint.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone)]
|
||||||
pub struct HttpClient {
|
pub struct HttpClient {
|
||||||
endpoint: ks_config::HttpEndpointConfig,
|
endpoint: ks_config::HttpEndpointConfig,
|
||||||
client: reqwest::Client,
|
client: reqwest::Client,
|
||||||
@@ -147,6 +156,16 @@ pub struct HttpClient {
|
|||||||
selected_role: std::option::Option<std::string::String>,
|
selected_role: std::option::Option<std::string::String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Debug for crate::HttpClient {
|
||||||
|
fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
return formatter
|
||||||
|
.debug_struct("HttpClient")
|
||||||
|
.field("endpoint", &"<redacted>")
|
||||||
|
.field("selected_role_configured", &self.selected_role.is_some())
|
||||||
|
.finish_non_exhaustive();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl crate::HttpClient {
|
impl crate::HttpClient {
|
||||||
/// Creates a new HTTP client bound to one endpoint.
|
/// Creates a new HTTP client bound to one endpoint.
|
||||||
pub fn new(endpoint: ks_config::HttpEndpointConfig) -> ks_core::Result<Self> {
|
pub fn new(endpoint: ks_config::HttpEndpointConfig) -> ks_core::Result<Self> {
|
||||||
@@ -207,11 +226,6 @@ impl crate::HttpClient {
|
|||||||
return self.endpoint.provider.as_str();
|
return self.endpoint.provider.as_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the endpoint URL.
|
|
||||||
pub fn endpoint_url(&self) -> &str {
|
|
||||||
return self.endpoint.url.as_str();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the endpoint configuration.
|
/// Returns the endpoint configuration.
|
||||||
pub fn endpoint_config(&self) -> &ks_config::HttpEndpointConfig {
|
pub fn endpoint_config(&self) -> &ks_config::HttpEndpointConfig {
|
||||||
return &self.endpoint;
|
return &self.endpoint;
|
||||||
@@ -230,7 +244,7 @@ impl crate::HttpClient {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a serializable endpoint snapshot.
|
/// Returns a backend-only endpoint snapshot without resolved URL material.
|
||||||
pub fn snapshot(&self) -> crate::HttpPoolClientSnapshot {
|
pub fn snapshot(&self) -> crate::HttpPoolClientSnapshot {
|
||||||
let mut roles = std::vec::Vec::new();
|
let mut roles = std::vec::Vec::new();
|
||||||
for role in &self.endpoint.roles {
|
for role in &self.endpoint.roles {
|
||||||
@@ -239,7 +253,6 @@ impl crate::HttpClient {
|
|||||||
return crate::HttpPoolClientSnapshot {
|
return crate::HttpPoolClientSnapshot {
|
||||||
endpoint_name: self.endpoint.name.clone(),
|
endpoint_name: self.endpoint.name.clone(),
|
||||||
provider: self.endpoint.provider.clone(),
|
provider: self.endpoint.provider.clone(),
|
||||||
endpoint_url: self.endpoint.url.clone(),
|
|
||||||
roles,
|
roles,
|
||||||
status: "active".to_string(),
|
status: "active".to_string(),
|
||||||
};
|
};
|
||||||
@@ -342,9 +355,10 @@ impl crate::HttpClient {
|
|||||||
let response = match response_result {
|
let response = match response_result {
|
||||||
std::result::Result::Ok(response) => response,
|
std::result::Result::Ok(response) => response,
|
||||||
std::result::Result::Err(error) => {
|
std::result::Result::Err(error) => {
|
||||||
tracing::error!(target: crate::TRACING_TARGET, action = "execute_http_json_rpc", endpoint_name = %self.endpoint.name, provider = %self.endpoint.provider, request_id, method = %method, retry_index, error = %error, "HTTP JSON-RPC transport failed");
|
let error_kind = reqwest_error_kind(&error);
|
||||||
|
tracing::error!(target: crate::TRACING_TARGET, action = "execute_http_json_rpc", endpoint_name = %self.endpoint.name, provider = %self.endpoint.provider, request_id, method = %method, retry_index, error_kind, "HTTP JSON-RPC transport failed");
|
||||||
return std::result::Result::Err(ks_core::Error::http(format!(
|
return std::result::Result::Err(ks_core::Error::http(format!(
|
||||||
"http json-rpc request '{}' failed on endpoint '{}': {error}",
|
"http json-rpc request '{}' failed on endpoint '{}' ({error_kind})",
|
||||||
method, self.endpoint.name
|
method, self.endpoint.name
|
||||||
)));
|
)));
|
||||||
},
|
},
|
||||||
@@ -355,9 +369,10 @@ impl crate::HttpClient {
|
|||||||
let text = match text_result {
|
let text = match text_result {
|
||||||
std::result::Result::Ok(text) => text,
|
std::result::Result::Ok(text) => text,
|
||||||
std::result::Result::Err(error) => {
|
std::result::Result::Err(error) => {
|
||||||
tracing::error!(target: crate::TRACING_TARGET, action = "execute_http_json_rpc", endpoint_name = %self.endpoint.name, provider = %self.endpoint.provider, request_id, method = %method, http_status = %status, retry_index, error = %error, "HTTP JSON-RPC response body read failed");
|
let error_kind = reqwest_error_kind(&error);
|
||||||
|
tracing::error!(target: crate::TRACING_TARGET, action = "execute_http_json_rpc", endpoint_name = %self.endpoint.name, provider = %self.endpoint.provider, request_id, method = %method, http_status = %status, retry_index, error_kind, "HTTP JSON-RPC response body read failed");
|
||||||
return std::result::Result::Err(ks_core::Error::http(format!(
|
return std::result::Result::Err(ks_core::Error::http(format!(
|
||||||
"cannot read http json-rpc response '{}' from endpoint '{}': {error}",
|
"cannot read http json-rpc response '{}' from endpoint '{}' ({error_kind})",
|
||||||
method, self.endpoint.name
|
method, self.endpoint.name
|
||||||
)));
|
)));
|
||||||
},
|
},
|
||||||
@@ -383,8 +398,8 @@ impl crate::HttpClient {
|
|||||||
if !status.is_success() {
|
if !status.is_success() {
|
||||||
tracing::error!(target: crate::TRACING_TARGET, action = "execute_http_json_rpc", endpoint_name = %self.endpoint.name, provider = %self.endpoint.provider, request_id, method = %method, http_status = %status, retry_index, response_byte_length = text.len(), "HTTP JSON-RPC endpoint returned non-success status");
|
tracing::error!(target: crate::TRACING_TARGET, action = "execute_http_json_rpc", endpoint_name = %self.endpoint.name, provider = %self.endpoint.provider, request_id, method = %method, http_status = %status, retry_index, response_byte_length = text.len(), "HTTP JSON-RPC endpoint returned non-success status");
|
||||||
return std::result::Result::Err(ks_core::Error::http(format!(
|
return std::result::Result::Err(ks_core::Error::http(format!(
|
||||||
"http json-rpc endpoint '{}' returned status {} after {} retries: {}",
|
"http json-rpc endpoint '{}' returned status {} after {} retries",
|
||||||
self.endpoint.name, status, retry_index, text
|
self.endpoint.name, status, retry_index
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
let parsed = match crate::parse_json_rpc_text(&text) {
|
let parsed = match crate::parse_json_rpc_text(&text) {
|
||||||
@@ -412,7 +427,7 @@ impl crate::HttpClient {
|
|||||||
},
|
},
|
||||||
std::option::Option::None => configured_pause_ms,
|
std::option::Option::None => configured_pause_ms,
|
||||||
};
|
};
|
||||||
tracing::warn!(target: crate::TRACING_TARGET, action = "retry_http_json_rpc_after_rate_limit", endpoint_name = %self.endpoint.name, provider = %self.endpoint.provider, request_id, method = %method, rpc_error_code = error_response.error.code, rpc_error_message = %error_response.error.message, retry_index, pause_ms, "HTTP JSON-RPC endpoint returned a rate-limit RPC error; retrying with bounded backoff");
|
tracing::warn!(target: crate::TRACING_TARGET, action = "retry_http_json_rpc_after_rate_limit", endpoint_name = %self.endpoint.name, provider = %self.endpoint.provider, request_id, method = %method, rpc_error_code = error_response.error.code, retry_index, pause_ms, "HTTP JSON-RPC endpoint returned a rate-limit RPC error; retrying with bounded backoff");
|
||||||
if let std::option::Option::Some(limiter) = &request_limiter {
|
if let std::option::Option::Some(limiter) = &request_limiter {
|
||||||
limiter.block_for(pause_ms).await;
|
limiter.block_for(pause_ms).await;
|
||||||
}
|
}
|
||||||
@@ -420,13 +435,10 @@ impl crate::HttpClient {
|
|||||||
continue;
|
continue;
|
||||||
},
|
},
|
||||||
crate::JsonRpcResponse::Error(error_response) => {
|
crate::JsonRpcResponse::Error(error_response) => {
|
||||||
tracing::error!(target: crate::TRACING_TARGET, action = "execute_http_json_rpc", endpoint_name = %self.endpoint.name, provider = %self.endpoint.provider, request_id, method = %method, retry_index, rpc_error_code = error_response.error.code, rpc_error_message = %error_response.error.message, "HTTP JSON-RPC endpoint returned an RPC error");
|
tracing::error!(target: crate::TRACING_TARGET, action = "execute_http_json_rpc", endpoint_name = %self.endpoint.name, provider = %self.endpoint.provider, request_id, method = %method, retry_index, rpc_error_code = error_response.error.code, "HTTP JSON-RPC endpoint returned an RPC error");
|
||||||
return std::result::Result::Err(ks_core::Error::http(format!(
|
return std::result::Result::Err(ks_core::Error::http(format!(
|
||||||
"json-rpc error {} from '{}' after {} retries: {}",
|
"json-rpc error {} from '{}' after {} retries",
|
||||||
error_response.error.code,
|
error_response.error.code, self.endpoint.name, retry_index
|
||||||
self.endpoint.name,
|
|
||||||
retry_index,
|
|
||||||
error_response.error.message
|
|
||||||
)));
|
)));
|
||||||
},
|
},
|
||||||
crate::JsonRpcResponse::Notification(_) => {
|
crate::JsonRpcResponse::Notification(_) => {
|
||||||
@@ -515,6 +527,25 @@ impl crate::HttpClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn reqwest_error_kind(error: &reqwest::Error) -> &'static str {
|
||||||
|
if error.is_timeout() {
|
||||||
|
return "timeout";
|
||||||
|
}
|
||||||
|
if error.is_connect() {
|
||||||
|
return "connect";
|
||||||
|
}
|
||||||
|
if error.is_request() {
|
||||||
|
return "request";
|
||||||
|
}
|
||||||
|
if error.is_body() {
|
||||||
|
return "body";
|
||||||
|
}
|
||||||
|
if error.is_decode() {
|
||||||
|
return "decode";
|
||||||
|
}
|
||||||
|
return "transport";
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
fn role_config(
|
fn role_config(
|
||||||
@@ -577,6 +608,27 @@ mod tests {
|
|||||||
assert!(client.can_handle("http_any", "send_transaction"));
|
assert!(client.can_handle("http_any", "send_transaction"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn debug_output_omits_endpoint_url() {
|
||||||
|
let mut endpoint = endpoint(true);
|
||||||
|
endpoint.url = "https://HTTP-SECRET-CANARY.invalid/?api-key=secret".to_string();
|
||||||
|
let client = match crate::HttpClient::new(endpoint) {
|
||||||
|
std::result::Result::Ok(client) => client,
|
||||||
|
std::result::Result::Err(error) => panic!("client creation failed: {error}"),
|
||||||
|
};
|
||||||
|
let rendered = format!("{client:?}");
|
||||||
|
assert!(rendered.contains("<redacted>"));
|
||||||
|
assert!(rendered.contains("selected_role_configured: false"));
|
||||||
|
assert!(!rendered.contains("HTTP-SECRET-CANARY"));
|
||||||
|
assert!(!rendered.contains("api-key=secret"));
|
||||||
|
let snapshot = client.snapshot();
|
||||||
|
let snapshot_rendered = format!("{snapshot:?}");
|
||||||
|
assert!(!snapshot_rendered.contains("endpoint_url"));
|
||||||
|
assert!(!snapshot_rendered.contains("endpointUrl"));
|
||||||
|
assert!(!snapshot_rendered.contains("HTTP-SECRET-CANARY"));
|
||||||
|
assert!(!snapshot_rendered.contains("api-key=secret"));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn snapshot_preserves_endpoint_metadata() {
|
fn snapshot_preserves_endpoint_metadata() {
|
||||||
let client = match crate::HttpClient::new(endpoint(true)) {
|
let client = match crate::HttpClient::new(endpoint(true)) {
|
||||||
@@ -586,7 +638,6 @@ mod tests {
|
|||||||
let snapshot = client.snapshot();
|
let snapshot = client.snapshot();
|
||||||
assert_eq!(snapshot.endpoint_name, "http_a");
|
assert_eq!(snapshot.endpoint_name, "http_a");
|
||||||
assert_eq!(snapshot.provider, "test");
|
assert_eq!(snapshot.provider, "test");
|
||||||
assert_eq!(snapshot.endpoint_url, "https://example.invalid");
|
|
||||||
assert_eq!(snapshot.roles.len(), 3);
|
assert_eq!(snapshot.roles.len(), 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// file: ks-onchain-transport/src/http_pool.rs
|
// file: ks-onchain-transport/src/http_pool.rs
|
||||||
// version: 10
|
// version: 11
|
||||||
|
|
||||||
//! HTTP endpoint pool and role-based routing.
|
//! HTTP endpoint pool and role-based routing.
|
||||||
|
|
||||||
@@ -53,7 +53,7 @@ impl crate::HttpEndpointPool {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a serializable snapshot of every endpoint in the pool.
|
/// Returns backend-only endpoint metadata without resolved URL material.
|
||||||
pub fn snapshot(&self) -> std::vec::Vec<crate::HttpPoolClientSnapshot> {
|
pub fn snapshot(&self) -> std::vec::Vec<crate::HttpPoolClientSnapshot> {
|
||||||
let mut snapshots = std::vec::Vec::new();
|
let mut snapshots = std::vec::Vec::new();
|
||||||
for client in &self.clients {
|
for client in &self.clients {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// file: ks-onchain-transport/src/ws_client.rs
|
// file: ks-onchain-transport/src/ws_client.rs
|
||||||
// version: 9
|
// version: 15
|
||||||
|
|
||||||
//! Standard Solana WebSocket client helpers.
|
//! Standard Solana WebSocket client helpers.
|
||||||
|
|
||||||
@@ -7,28 +7,46 @@ use futures_util::SinkExt; // rust-rules: trait-import
|
|||||||
use futures_util::StreamExt; // rust-rules: trait-import
|
use futures_util::StreamExt; // rust-rules: trait-import
|
||||||
|
|
||||||
/// Snapshot of one pooled WebSocket endpoint.
|
/// Snapshot of one pooled WebSocket endpoint.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize)]
|
#[derive(Clone, Eq, PartialEq)]
|
||||||
#[serde(rename_all = "camelCase")]
|
|
||||||
pub struct WsPoolClientSnapshot {
|
pub struct WsPoolClientSnapshot {
|
||||||
/// Logical endpoint name.
|
/// Logical endpoint name.
|
||||||
pub endpoint_name: std::string::String,
|
pub endpoint_name: std::string::String,
|
||||||
/// Provider name.
|
/// Provider name.
|
||||||
pub provider: std::string::String,
|
pub provider: std::string::String,
|
||||||
/// Endpoint URL.
|
|
||||||
pub endpoint_url: std::string::String,
|
|
||||||
/// Supported roles.
|
/// Supported roles.
|
||||||
pub roles: std::vec::Vec<crate::EndpointRoleSnapshot>,
|
pub roles: std::vec::Vec<crate::EndpointRoleSnapshot>,
|
||||||
/// Status string.
|
/// Status string.
|
||||||
pub status: std::string::String,
|
pub status: std::string::String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Debug for crate::WsPoolClientSnapshot {
|
||||||
|
fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
return formatter
|
||||||
|
.debug_struct("WsPoolClientSnapshot")
|
||||||
|
.field("endpoint_name", &self.endpoint_name)
|
||||||
|
.field("provider", &self.provider)
|
||||||
|
.field("roles", &self.roles)
|
||||||
|
.field("status", &self.status)
|
||||||
|
.finish();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Standard Solana WebSocket client bound to one configured endpoint.
|
/// Standard Solana WebSocket client bound to one configured endpoint.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone)]
|
||||||
pub struct WsClient {
|
pub struct WsClient {
|
||||||
endpoint: ks_config::WsEndpointConfig,
|
endpoint: ks_config::WsEndpointConfig,
|
||||||
next_request_id: std::sync::Arc<std::sync::atomic::AtomicU64>,
|
next_request_id: std::sync::Arc<std::sync::atomic::AtomicU64>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Debug for crate::WsClient {
|
||||||
|
fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
return formatter
|
||||||
|
.debug_struct("WsClient")
|
||||||
|
.field("endpoint", &"<redacted>")
|
||||||
|
.finish_non_exhaustive();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl crate::WsClient {
|
impl crate::WsClient {
|
||||||
/// Creates a new WebSocket client bound to one endpoint.
|
/// Creates a new WebSocket client bound to one endpoint.
|
||||||
pub fn new(endpoint: ks_config::WsEndpointConfig) -> ks_core::Result<Self> {
|
pub fn new(endpoint: ks_config::WsEndpointConfig) -> ks_core::Result<Self> {
|
||||||
@@ -56,8 +74,7 @@ impl crate::WsClient {
|
|||||||
return self.endpoint.provider.as_str();
|
return self.endpoint.provider.as_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the endpoint URL.
|
pub(crate) fn endpoint_url(&self) -> &str {
|
||||||
pub fn endpoint_url(&self) -> &str {
|
|
||||||
return self.endpoint.url.as_str();
|
return self.endpoint.url.as_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,7 +96,7 @@ impl crate::WsClient {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a serializable endpoint snapshot.
|
/// Returns a backend-only endpoint snapshot without resolved URL material.
|
||||||
pub fn snapshot(&self) -> crate::WsPoolClientSnapshot {
|
pub fn snapshot(&self) -> crate::WsPoolClientSnapshot {
|
||||||
let mut roles = std::vec::Vec::new();
|
let mut roles = std::vec::Vec::new();
|
||||||
for role in &self.endpoint.roles {
|
for role in &self.endpoint.roles {
|
||||||
@@ -88,7 +105,6 @@ impl crate::WsClient {
|
|||||||
return crate::WsPoolClientSnapshot {
|
return crate::WsPoolClientSnapshot {
|
||||||
endpoint_name: self.endpoint.name.clone(),
|
endpoint_name: self.endpoint.name.clone(),
|
||||||
provider: self.endpoint.provider.clone(),
|
provider: self.endpoint.provider.clone(),
|
||||||
endpoint_url: self.endpoint.url.clone(),
|
|
||||||
roles,
|
roles,
|
||||||
status: "idle".to_string(),
|
status: "idle".to_string(),
|
||||||
};
|
};
|
||||||
@@ -156,10 +172,10 @@ impl crate::WsClient {
|
|||||||
};
|
};
|
||||||
let (mut stream, _response) = match connect_result {
|
let (mut stream, _response) = match connect_result {
|
||||||
std::result::Result::Ok(pair) => pair,
|
std::result::Result::Ok(pair) => pair,
|
||||||
std::result::Result::Err(error) => {
|
std::result::Result::Err(_error) => {
|
||||||
tracing::error!(target: crate::TRACING_TARGET, action = "connect_ws_endpoint", endpoint_name = %self.endpoint.name, provider = %self.endpoint.provider, request_id = ?request.id, method = %method, error = %error, "WebSocket endpoint connection failed");
|
tracing::error!(target: crate::TRACING_TARGET, action = "connect_ws_endpoint", endpoint_name = %self.endpoint.name, provider = %self.endpoint.provider, request_id = ?request.id, method = %method, error_kind = "connect", "WebSocket endpoint connection failed");
|
||||||
return std::result::Result::Err(ks_core::Error::ws(format!(
|
return std::result::Result::Err(ks_core::Error::ws(format!(
|
||||||
"cannot connect websocket endpoint '{}': {error}",
|
"cannot connect websocket endpoint '{}'",
|
||||||
self.endpoint.name
|
self.endpoint.name
|
||||||
)));
|
)));
|
||||||
},
|
},
|
||||||
@@ -217,7 +233,7 @@ impl crate::WsClient {
|
|||||||
match parse_result {
|
match parse_result {
|
||||||
std::result::Result::Ok(response) => {
|
std::result::Result::Ok(response) => {
|
||||||
if let crate::JsonRpcResponse::Error(error_response) = &response {
|
if let crate::JsonRpcResponse::Error(error_response) = &response {
|
||||||
tracing::error!(target: crate::TRACING_TARGET, action = "execute_ws_json_rpc_once", endpoint_name = %self.endpoint.name, provider = %self.endpoint.provider, request_id = ?request.id, method = %method, response_kind = response.kind_name(), rpc_error_code = error_response.error.code, rpc_error_message = %error_response.error.message, "WebSocket JSON-RPC endpoint returned an RPC error");
|
tracing::error!(target: crate::TRACING_TARGET, action = "execute_ws_json_rpc_once", endpoint_name = %self.endpoint.name, provider = %self.endpoint.provider, request_id = ?request.id, method = %method, response_kind = response.kind_name(), rpc_error_code = error_response.error.code, "WebSocket JSON-RPC endpoint returned an RPC error");
|
||||||
} else {
|
} else {
|
||||||
tracing::debug!(target: crate::TRACING_TARGET, action = "execute_ws_json_rpc_once", endpoint_name = %self.endpoint.name, provider = %self.endpoint.provider, request_id = ?request.id, method = %method, response_kind = response.kind_name(), "one-shot WebSocket JSON-RPC request completed");
|
tracing::debug!(target: crate::TRACING_TARGET, action = "execute_ws_json_rpc_once", endpoint_name = %self.endpoint.name, provider = %self.endpoint.provider, request_id = ?request.id, method = %method, response_kind = response.kind_name(), "one-shot WebSocket JSON-RPC request completed");
|
||||||
}
|
}
|
||||||
@@ -334,6 +350,26 @@ mod tests {
|
|||||||
assert!(client.can_handle("ws_any", "logs_subscribe_mentions"));
|
assert!(client.can_handle("ws_any", "logs_subscribe_mentions"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn debug_output_omits_endpoint_url() {
|
||||||
|
let mut endpoint = endpoint(true);
|
||||||
|
endpoint.url = "wss://WS-SECRET-CANARY.invalid/?api-key=secret".to_string();
|
||||||
|
let client = match crate::WsClient::new(endpoint) {
|
||||||
|
std::result::Result::Ok(client) => client,
|
||||||
|
std::result::Result::Err(error) => panic!("client creation failed: {error}"),
|
||||||
|
};
|
||||||
|
let rendered = format!("{client:?}");
|
||||||
|
assert!(rendered.contains("<redacted>"));
|
||||||
|
assert!(!rendered.contains("WS-SECRET-CANARY"));
|
||||||
|
assert!(!rendered.contains("api-key=secret"));
|
||||||
|
let snapshot = client.snapshot();
|
||||||
|
let snapshot_rendered = format!("{snapshot:?}");
|
||||||
|
assert!(!snapshot_rendered.contains("endpoint_url"));
|
||||||
|
assert!(!snapshot_rendered.contains("endpointUrl"));
|
||||||
|
assert!(!snapshot_rendered.contains("WS-SECRET-CANARY"));
|
||||||
|
assert!(!snapshot_rendered.contains("api-key=secret"));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn snapshot_preserves_endpoint_metadata() {
|
fn snapshot_preserves_endpoint_metadata() {
|
||||||
let client = match crate::WsClient::new(endpoint(true)) {
|
let client = match crate::WsClient::new(endpoint(true)) {
|
||||||
@@ -343,7 +379,6 @@ mod tests {
|
|||||||
let snapshot = client.snapshot();
|
let snapshot = client.snapshot();
|
||||||
assert_eq!(snapshot.endpoint_name, "ws_a");
|
assert_eq!(snapshot.endpoint_name, "ws_a");
|
||||||
assert_eq!(snapshot.provider, "test");
|
assert_eq!(snapshot.provider, "test");
|
||||||
assert_eq!(snapshot.endpoint_url, "wss://example.invalid");
|
|
||||||
assert_eq!(snapshot.roles.len(), 3);
|
assert_eq!(snapshot.roles.len(), 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// file: ks-onchain-transport/src/ws_pool.rs
|
// file: ks-onchain-transport/src/ws_pool.rs
|
||||||
// version: 8
|
// version: 9
|
||||||
|
|
||||||
//! WebSocket endpoint pool and role-based routing.
|
//! WebSocket endpoint pool and role-based routing.
|
||||||
|
|
||||||
@@ -53,7 +53,7 @@ impl crate::WsEndpointPool {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a serializable snapshot of every endpoint in the pool.
|
/// Returns backend-only endpoint metadata without resolved URL material.
|
||||||
pub fn snapshot(&self) -> std::vec::Vec<crate::WsPoolClientSnapshot> {
|
pub fn snapshot(&self) -> std::vec::Vec<crate::WsPoolClientSnapshot> {
|
||||||
let mut snapshots = std::vec::Vec::new();
|
let mut snapshots = std::vec::Vec::new();
|
||||||
for client in &self.clients {
|
for client in &self.clients {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// file: ks-onchain-transport/src/ws_session.rs
|
// file: ks-onchain-transport/src/ws_session.rs
|
||||||
// version: 6
|
// version: 9
|
||||||
|
|
||||||
//! Persistent multiplexed WebSocket session with bounded reconnect and resubscription.
|
//! Persistent multiplexed WebSocket session with bounded reconnect and resubscription.
|
||||||
|
|
||||||
@@ -100,15 +100,12 @@ pub struct WsSubscriptionSnapshot {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Current snapshot of one persistent WebSocket session.
|
/// Current snapshot of one persistent WebSocket session.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
#[derive(Clone, Eq, PartialEq)]
|
||||||
#[serde(rename_all = "camelCase")]
|
|
||||||
pub struct WsSessionSnapshot {
|
pub struct WsSessionSnapshot {
|
||||||
/// Endpoint name.
|
/// Endpoint name.
|
||||||
pub endpoint_name: std::string::String,
|
pub endpoint_name: std::string::String,
|
||||||
/// Provider name.
|
/// Provider name.
|
||||||
pub provider: std::string::String,
|
pub provider: std::string::String,
|
||||||
/// Endpoint URL.
|
|
||||||
pub endpoint_url: std::string::String,
|
|
||||||
/// Current lifecycle state.
|
/// Current lifecycle state.
|
||||||
pub state: crate::WsSessionState,
|
pub state: crate::WsSessionState,
|
||||||
/// Number of successful reconnects since session creation.
|
/// Number of successful reconnects since session creation.
|
||||||
@@ -119,6 +116,20 @@ pub struct WsSessionSnapshot {
|
|||||||
pub subscriptions: std::vec::Vec<crate::WsSubscriptionSnapshot>,
|
pub subscriptions: std::vec::Vec<crate::WsSubscriptionSnapshot>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Debug for crate::WsSessionSnapshot {
|
||||||
|
fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
return formatter
|
||||||
|
.debug_struct("WsSessionSnapshot")
|
||||||
|
.field("endpoint_name", &self.endpoint_name)
|
||||||
|
.field("provider", &self.provider)
|
||||||
|
.field("state", &self.state)
|
||||||
|
.field("reconnect_count", &self.reconnect_count)
|
||||||
|
.field("capabilities", &self.capabilities)
|
||||||
|
.field("subscriptions", &self.subscriptions)
|
||||||
|
.finish();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Successful subscription acknowledgement.
|
/// Successful subscription acknowledgement.
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub struct WsSubscriptionAck {
|
pub struct WsSubscriptionAck {
|
||||||
@@ -202,7 +213,6 @@ impl std::fmt::Debug for crate::WsSession {
|
|||||||
.debug_struct("WsSession")
|
.debug_struct("WsSession")
|
||||||
.field("endpoint_name", &self.endpoint.name)
|
.field("endpoint_name", &self.endpoint.name)
|
||||||
.field("provider", &self.endpoint.provider)
|
.field("provider", &self.endpoint.provider)
|
||||||
.field("endpoint_url", &self.endpoint.url)
|
|
||||||
.finish_non_exhaustive();
|
.finish_non_exhaustive();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -238,7 +248,6 @@ impl crate::WsSession {
|
|||||||
let snapshot = std::sync::Arc::new(tokio::sync::RwLock::new(crate::WsSessionSnapshot {
|
let snapshot = std::sync::Arc::new(tokio::sync::RwLock::new(crate::WsSessionSnapshot {
|
||||||
endpoint_name: endpoint.name.clone(),
|
endpoint_name: endpoint.name.clone(),
|
||||||
provider: endpoint.provider.clone(),
|
provider: endpoint.provider.clone(),
|
||||||
endpoint_url: endpoint.url.clone(),
|
|
||||||
state: crate::WsSessionState::Connected,
|
state: crate::WsSessionState::Connected,
|
||||||
reconnect_count: 0,
|
reconnect_count: 0,
|
||||||
capabilities: initial_capabilities,
|
capabilities: initial_capabilities,
|
||||||
@@ -788,10 +797,8 @@ impl WsSessionRuntime {
|
|||||||
|
|
||||||
async fn handle_error_response(&mut self, error_response: crate::JsonRpcErrorResponse) {
|
async fn handle_error_response(&mut self, error_response: crate::JsonRpcErrorResponse) {
|
||||||
let request_id = error_response.id.as_u64();
|
let request_id = error_response.id.as_u64();
|
||||||
let error = ks_core::Error::ws(format!(
|
let error =
|
||||||
"WebSocket JSON-RPC error {}: {}",
|
ks_core::Error::ws(format!("WebSocket JSON-RPC error {}", error_response.error.code));
|
||||||
error_response.error.code, error_response.error.message
|
|
||||||
));
|
|
||||||
if let std::option::Option::Some(request_id) = request_id {
|
if let std::option::Option::Some(request_id) = request_id {
|
||||||
if let std::option::Option::Some(pending) = self.pending.remove(&request_id) {
|
if let std::option::Option::Some(pending) = self.pending.remove(&request_id) {
|
||||||
match pending {
|
match pending {
|
||||||
@@ -852,10 +859,8 @@ impl WsSessionRuntime {
|
|||||||
self.emit_diagnostic(
|
self.emit_diagnostic(
|
||||||
"ws_capability_disabled",
|
"ws_capability_disabled",
|
||||||
format!(
|
format!(
|
||||||
"endpoint '{}' rejected unstable method '{method}'; capability disabled for this session: JSON-RPC {} {}",
|
"endpoint '{}' rejected unstable method '{method}'; capability disabled for this session: JSON-RPC {}",
|
||||||
self.client.endpoint_name(),
|
self.client.endpoint_name(), error_response.error.code
|
||||||
error_response.error.code,
|
|
||||||
error_response.error.message
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -1180,8 +1185,8 @@ async fn connect_stream(client: &crate::WsClient) -> ks_core::Result<WsStream> {
|
|||||||
};
|
};
|
||||||
return match connect_result {
|
return match connect_result {
|
||||||
std::result::Result::Ok((stream, _response)) => std::result::Result::Ok(stream),
|
std::result::Result::Ok((stream, _response)) => std::result::Result::Ok(stream),
|
||||||
std::result::Result::Err(error) => std::result::Result::Err(ks_core::Error::ws(format!(
|
std::result::Result::Err(_error) => std::result::Result::Err(ks_core::Error::ws(format!(
|
||||||
"cannot connect WebSocket endpoint '{}': {error}",
|
"cannot connect WebSocket endpoint '{}'",
|
||||||
client.endpoint_name()
|
client.endpoint_name()
|
||||||
))),
|
))),
|
||||||
};
|
};
|
||||||
@@ -1281,6 +1286,21 @@ mod tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn session_snapshot_debug_contains_no_endpoint_url_field() {
|
||||||
|
let snapshot = crate::WsSessionSnapshot {
|
||||||
|
endpoint_name: "helius".to_string(),
|
||||||
|
provider: "helius".to_string(),
|
||||||
|
state: crate::WsSessionState::Connected,
|
||||||
|
reconnect_count: 0,
|
||||||
|
capabilities: crate::StandardWsCapabilities::default(),
|
||||||
|
subscriptions: std::vec::Vec::new(),
|
||||||
|
};
|
||||||
|
let rendered = format!("{snapshot:?}");
|
||||||
|
assert!(!rendered.contains("endpoint_url"));
|
||||||
|
assert!(!rendered.contains("endpointUrl"));
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn persistent_session_multiplexes_notification_and_explicit_unsubscribe() {
|
async fn persistent_session_multiplexes_notification_and_explicit_unsubscribe() {
|
||||||
let listener = match tokio::net::TcpListener::bind("127.0.0.1:0").await {
|
let listener = match tokio::net::TcpListener::bind("127.0.0.1:0").await {
|
||||||
|
|||||||
@@ -32,17 +32,17 @@ Cette orientation générale est aussi conservée dans `docs/IDEA_REMINDERS.md`.
|
|||||||
|
|
||||||
Les crates suivantes sont des bibliothèques ou composants de support Solana généralistes et sont donc candidates au renommage direct en `0.5.1` :
|
Les crates suivantes sont des bibliothèques ou composants de support Solana généralistes et sont donc candidates au renommage direct en `0.5.1` :
|
||||||
|
|
||||||
| Actuel | Cible de travail |
|
| Actuel | Cible de travail |
|
||||||
|---|---|
|
|------------------------------|------------------------------------------------------------------------------------------|
|
||||||
| `kb-core` | `ks-core` |
|
| `kb-core` | `ks-core` |
|
||||||
| `kb-config` | `ks-config` |
|
| `kb-config` | `ks-config` |
|
||||||
| `kb-lib` | `ks-lib` |
|
| `kb-lib` | `ks-lib` |
|
||||||
| `kb-logging` | `ks-logging` |
|
| `kb-logging` | `ks-logging` |
|
||||||
| `kb-program-ids` | `ks-program-ids` |
|
| `kb-program-ids` | `ks-program-ids` |
|
||||||
| `kb-pipeline` | `ks-pipeline` |
|
| `kb-pipeline` | `ks-pipeline` |
|
||||||
| `kb-onchain-transport` | `ks-onchain-transport` |
|
| `kb-onchain-transport` | `ks-onchain-transport` |
|
||||||
| `kb-store` | `ks-store` |
|
| `kb-store` | `ks-store` |
|
||||||
| `kb-wallet` | `ks-wallet` |
|
| `kb-wallet` | `ks-wallet` |
|
||||||
| `kb-pipeline-demo-scenarios` | `ks-pipeline-demo-scenarios` à confirmer comme composant de validation Khadhroony Solana |
|
| `kb-pipeline-demo-scenarios` | `ks-pipeline-demo-scenarios` à confirmer comme composant de validation Khadhroony Solana |
|
||||||
|
|
||||||
`kb-app-demo-desktop` reste hors de cette substitution automatique : c'est une application Khadhroony Bot, même si son rôle courant est surtout de tester les composants `ks-*`.
|
`kb-app-demo-desktop` reste hors de cette substitution automatique : c'est une application Khadhroony Bot, même si son rôle courant est surtout de tester les composants `ks-*`.
|
||||||
@@ -121,13 +121,13 @@ En revanche :
|
|||||||
|
|
||||||
Le contrat `0.5.3` doit donc imposer la distinction suivante :
|
Le contrat `0.5.3` doit donc imposer la distinction suivante :
|
||||||
|
|
||||||
| Dimension | Sens |
|
| Dimension | Sens |
|
||||||
|---|---|
|
|-------------------------------------------------|----------------------------------------------------------|
|
||||||
| `slot` | ordre/position Solana ; jamais assimilé à un temps civil |
|
| `slot` | ordre/position Solana ; jamais assimilé à un temps civil |
|
||||||
| `block_time` | temps on-chain Unix optionnel observé depuis le cluster |
|
| `block_time` | temps on-chain Unix optionnel observé depuis le cluster |
|
||||||
| `detected_at` / `received_at` / `normalized_at` | temps locaux d'acquisition |
|
| `detected_at` / `received_at` / `normalized_at` | temps locaux d'acquisition |
|
||||||
| `persisted_at` | instant d'écriture de l'observation |
|
| `persisted_at` | instant d'écriture de l'observation |
|
||||||
| `created_at` / `updated_at` | cycle de vie de la ligne SQL |
|
| `created_at` / `updated_at` | cycle de vie de la ligne SQL |
|
||||||
|
|
||||||
Une requête de prix ou série temporelle ne doit jamais prendre `created_at` comme substitut implicite de `block_time`.
|
Une requête de prix ou série temporelle ne doit jamais prendre `created_at` comme substitut implicite de `block_time`.
|
||||||
|
|
||||||
@@ -211,16 +211,16 @@ L'inventaire statique de `kb-lib` trouve :
|
|||||||
|
|
||||||
Les huit exécuteurs actifs sont :
|
Les huit exécuteurs actifs sont :
|
||||||
|
|
||||||
| Exécuteur actif | Scénario réutilisable actuel | Qualification |
|
| Exécuteur actif | Scénario réutilisable actuel | Qualification |
|
||||||
|---|---|---|
|
|------------------------------|------------------------------|-----------------------------------------------------------------|
|
||||||
| Solana Core | oui | plusieurs parcours Devnet ; matrice native existante |
|
| Solana Core | oui | plusieurs parcours Devnet ; matrice native existante |
|
||||||
| SPL Memo v4 | oui | Devnet ; v1/v3 restent decode-only |
|
| SPL Memo v4 | oui | Devnet ; v1/v3 restent decode-only |
|
||||||
| SPL Associated Token Account | oui | scénario Devnet |
|
| SPL Associated Token Account | oui | scénario Devnet |
|
||||||
| SPL Token classique | oui | scénarios et lifecycle Devnet |
|
| SPL Token classique | oui | scénarios et lifecycle Devnet |
|
||||||
| SPL Token-2022 | oui | scénarios Devnet et campagne Token Metadata |
|
| SPL Token-2022 | oui | scénarios Devnet et campagne Token Metadata |
|
||||||
| SPL ElGamal registry | non | implémenté + synthétique seulement ; preuve réseau indisponible |
|
| SPL ElGamal registry | non | implémenté + synthétique seulement ; preuve réseau indisponible |
|
||||||
| Metaplex Token Metadata | oui | matrice `15 confirmed / 5 unavailable` |
|
| Metaplex Token Metadata | oui | matrice `15 confirmed / 5 unavailable` |
|
||||||
| Solana Program Metadata | oui | 9 opérations confirmées Devnet |
|
| Solana Program Metadata | oui | 9 opérations confirmées Devnet |
|
||||||
|
|
||||||
Le seul exécuteur actif sans scénario réseau réutilisable est donc ElGamal, et son absence est **`unavailable`/report conditionnel**, pas `implement`, tant qu'une nouvelle possibilité de preuve n'existe pas.
|
Le seul exécuteur actif sans scénario réseau réutilisable est donc ElGamal, et son absence est **`unavailable`/report conditionnel**, pas `implement`, tant qu'une nouvelle possibilité de preuve n'existe pas.
|
||||||
|
|
||||||
@@ -284,18 +284,18 @@ La future matrice transversale doit comparer uniquement les **surfaces actives o
|
|||||||
|
|
||||||
Pour chaque capacité, enregistrer :
|
Pour chaque capacité, enregistrer :
|
||||||
|
|
||||||
| Dimension | Valeur attendue |
|
| Dimension | Valeur attendue |
|
||||||
|---|---|
|
|-------------------|---------------------------------------------------------------------------------------|
|
||||||
| decoder | actif / réservé / absent |
|
| decoder | actif / réservé / absent |
|
||||||
| materializer | actif / state-only / réservé / non applicable |
|
| materializer | actif / state-only / réservé / non applicable |
|
||||||
| executor | actif / decode-only / deprecated / réservé / absent |
|
| executor | actif / decode-only / deprecated / réservé / absent |
|
||||||
| synthetic | présent / absent / non applicable |
|
| synthetic | présent / absent / non applicable |
|
||||||
| reusable scenario | présent / absent / unavailable / non applicable |
|
| reusable scenario | présent / absent / unavailable / non applicable |
|
||||||
| simulation | prouvée / non exécutée / unavailable |
|
| simulation | prouvée / non exécutée / unavailable |
|
||||||
| submission | confirmed / non exécutée / unsafe / unavailable |
|
| submission | confirmed / non exécutée / unsafe / unavailable |
|
||||||
| postcondition | stateful / replay/materialization / non applicable |
|
| postcondition | stateful / replay/materialization / non applicable |
|
||||||
| desktop | adaptateur / logique réutilisable résiduelle / absent |
|
| desktop | adaptateur / logique réutilisable résiduelle / absent |
|
||||||
| final status | `implement`, `decode-only`, `deprecated`, `unavailable`, `not-applicable`, `deferred` |
|
| final status | `implement`, `decode-only`, `deprecated`, `unavailable`, `not-applicable`, `deferred` |
|
||||||
|
|
||||||
### Classification actuelle de départ
|
### Classification actuelle de départ
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<!-- file: prompts/030_v0_5_1_khadhroony_solana_namespace_and_config.md -->
|
<!-- file: prompts/030_v0_5_1_khadhroony_solana_namespace_and_config.md -->
|
||||||
<!-- version: 5 -->
|
<!-- version: 6 -->
|
||||||
|
|
||||||
# Khadhroony Bot3 — `0.5.1` — migration Khadhroony Solana et configuration sûre
|
# Khadhroony Bot3 — `0.5.1` — migration Khadhroony Solana et configuration sûre
|
||||||
|
|
||||||
@@ -351,11 +351,12 @@ Le détail doit être confirmé par `0.5.1-pre.001`, mais la trajectoire cible e
|
|||||||
|
|
||||||
### `0.5.1-pre.008` — runtime/public, camouflage et Tauri sûr
|
### `0.5.1-pre.008` — runtime/public, camouflage et Tauri sûr
|
||||||
|
|
||||||
- séparer source/runtime/public/diagnostic ;
|
- **réalisé** : rendre les contrats `ks-config` source/runtime sensibles backend-only, sans `Serialize`/`Debug` ;
|
||||||
- propager la sensibilité des valeurs composées ;
|
- **réalisé** : rendre `application` opaque pour `ks-config` et valider le fragment desktop avec son schéma propriétaire ;
|
||||||
- supprimer les payloads de config complète ;
|
- **réalisé** : remplacer l'exposition `AppConfig/ProfileConfig` par des DTO public/diagnostic construits explicitement ;
|
||||||
- diagnostics sûrs et camouflage systématique ;
|
- **réalisé** : propager `Secret > Internal > Public` aux chaînes composées et supprimer l'écho de valeurs rejetées dans les erreurs de validation ;
|
||||||
- tests de non-divulgation et TS-RS aligné.
|
- **réalisé** : retirer TS-RS et les bindings générés de `ks-config`/`ks-lib`, avec audit empêchant leur réintroduction implicite ;
|
||||||
|
- **réalisé** : ajouter les canaris de non-divulgation et le test d'API externe de sensibilité.
|
||||||
|
|
||||||
### `0.5.1-pre.009` — réconciliation et clôture
|
### `0.5.1-pre.009` — réconciliation et clôture
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# file: scripts/audit_khadhroony_workspace_rules.py
|
# file: scripts/audit_khadhroony_workspace_rules.py
|
||||||
# version: 23
|
# version: 28
|
||||||
|
|
||||||
"""Audit mechanically verifiable rules specific to khadhroony-bot3."""
|
"""Audit mechanically verifiable rules specific to khadhroony-bot3."""
|
||||||
|
|
||||||
@@ -915,13 +915,13 @@ def audit_environment_namespaces(root: pathlib.Path) -> list[Violation]:
|
|||||||
"config/store.config.json",
|
"config/store.config.json",
|
||||||
"config/wallet.config.json",
|
"config/wallet.config.json",
|
||||||
"config/execution.config.json",
|
"config/execution.config.json",
|
||||||
"config/example.kb-app-demo-desktop.default.config.json",
|
"config/exemples/example.kb-app-demo-desktop.default.config.json",
|
||||||
"config/example.logging.config.json",
|
"config/exemples/example.logging.config.json",
|
||||||
"config/example.transport.config.json",
|
"config/exemples/example.transport.config.json",
|
||||||
"config/example.listeners.config.json",
|
"config/exemples/example.listeners.config.json",
|
||||||
"config/example.store.config.json",
|
"config/exemples/example.store.config.json",
|
||||||
"config/example.wallet.config.json",
|
"config/exemples/example.wallet.config.json",
|
||||||
"config/example.execution.config.json",
|
"config/exemples/example.execution.config.json",
|
||||||
]:
|
]:
|
||||||
config = root / relative
|
config = root / relative
|
||||||
if not config.is_file():
|
if not config.is_file():
|
||||||
@@ -970,14 +970,15 @@ def audit_configuration_split(root: pathlib.Path) -> list[Violation]:
|
|||||||
"config/store.config.json",
|
"config/store.config.json",
|
||||||
"config/wallet.config.json",
|
"config/wallet.config.json",
|
||||||
"config/execution.config.json",
|
"config/execution.config.json",
|
||||||
"config/example.kb-app-demo-desktop.default.config.json",
|
"config/exemples/example.kb-app-demo-desktop.default.config.json",
|
||||||
"config/example.logging.config.json",
|
"config/exemples/example.logging.config.json",
|
||||||
"config/example.transport.config.json",
|
"config/exemples/example.transport.config.json",
|
||||||
"config/example.listeners.config.json",
|
"config/exemples/example.listeners.config.json",
|
||||||
"config/example.store.config.json",
|
"config/exemples/example.store.config.json",
|
||||||
"config/example.wallet.config.json",
|
"config/exemples/example.wallet.config.json",
|
||||||
"config/example.execution.config.json",
|
"config/exemples/example.execution.config.json",
|
||||||
"config/schemas/composition.config.schema.json",
|
"config/schemas/composition.config.schema.json",
|
||||||
|
"config/schemas/kb-app-demo-desktop.application.config.schema.json",
|
||||||
"config/schemas/logging.config.schema.json",
|
"config/schemas/logging.config.schema.json",
|
||||||
"config/schemas/transport.config.schema.json",
|
"config/schemas/transport.config.schema.json",
|
||||||
"config/schemas/listeners.config.schema.json",
|
"config/schemas/listeners.config.schema.json",
|
||||||
@@ -1062,6 +1063,13 @@ def audit_configuration_split(root: pathlib.Path) -> list[Violation]:
|
|||||||
"config/example.app.config.json",
|
"config/example.app.config.json",
|
||||||
"config/schemas/app.config.schema.json",
|
"config/schemas/app.config.schema.json",
|
||||||
"config/example.config.json",
|
"config/example.config.json",
|
||||||
|
"config/example.kb-app-demo-desktop.default.config.json",
|
||||||
|
"config/example.logging.config.json",
|
||||||
|
"config/example.transport.config.json",
|
||||||
|
"config/example.listeners.config.json",
|
||||||
|
"config/example.store.config.json",
|
||||||
|
"config/example.wallet.config.json",
|
||||||
|
"config/example.execution.config.json",
|
||||||
"config/schema.config.json",
|
"config/schema.config.json",
|
||||||
"config/ks-pipeline-demo-scenarios.default.config.json",
|
"config/ks-pipeline-demo-scenarios.default.config.json",
|
||||||
]
|
]
|
||||||
@@ -1069,9 +1077,238 @@ def audit_configuration_split(root: pathlib.Path) -> list[Violation]:
|
|||||||
if not (root / relative).exists():
|
if not (root / relative).exists():
|
||||||
continue
|
continue
|
||||||
violations.append(Violation("KH_CFG007", relative, 1, "legacy or unnecessary configuration composition file must be removed"))
|
violations.append(Violation("KH_CFG007", relative, 1, "legacy or unnecessary configuration composition file must be removed"))
|
||||||
|
protected_runtime_files = [
|
||||||
|
"ks-config/src/composition.rs",
|
||||||
|
"ks-config/src/execution.rs",
|
||||||
|
"ks-config/src/listeners.rs",
|
||||||
|
"ks-config/src/settings.rs",
|
||||||
|
"ks-config/src/store.rs",
|
||||||
|
"ks-config/src/transport.rs",
|
||||||
|
"ks-config/src/wallet.rs",
|
||||||
|
]
|
||||||
|
for relative in protected_runtime_files:
|
||||||
|
path = root / relative
|
||||||
|
if not path.is_file():
|
||||||
|
continue
|
||||||
|
for index, line in enumerate(path.read_text(encoding="utf-8").splitlines(), 1):
|
||||||
|
if "#[derive(" not in line:
|
||||||
|
continue
|
||||||
|
if "serde::Serialize" in line:
|
||||||
|
violations.append(Violation("KH_CFG013", relative, index, "resolved/source configuration contracts must not derive Serialize because they may contain resolved secrets"))
|
||||||
|
if re.search(r"\bDebug\b", line):
|
||||||
|
violations.append(Violation("KH_CFG014", relative, index, "resolved/source configuration contracts must not derive Debug because they may contain resolved secrets or internal values"))
|
||||||
return violations
|
return violations
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def audit_ts_rs_boundaries(root: pathlib.Path) -> list[Violation]:
|
||||||
|
"""Keep TS-RS generation at explicit application boundaries."""
|
||||||
|
|
||||||
|
violations: list[Violation] = []
|
||||||
|
for cargo in sorted(root.glob("ks-*/Cargo.toml")):
|
||||||
|
crate = cargo.parent
|
||||||
|
data = tomllib.loads(cargo.read_text(encoding="utf-8"))
|
||||||
|
for section in ["dependencies", "dev-dependencies", "build-dependencies"]:
|
||||||
|
dependencies = data.get(section, {})
|
||||||
|
if "ts-rs" in dependencies:
|
||||||
|
violations.append(
|
||||||
|
Violation(
|
||||||
|
"KH_TS001",
|
||||||
|
cargo.relative_to(root).as_posix(),
|
||||||
|
1,
|
||||||
|
"generic ks-* crates must not depend on ts-rs without an explicit approved external TypeScript contract",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
for path in sorted((crate / "src").rglob("*.rs")):
|
||||||
|
relative = path.relative_to(root).as_posix()
|
||||||
|
for index, line in enumerate(path.read_text(encoding="utf-8").splitlines(), 1):
|
||||||
|
if "ts_rs::" in line or "#[ts(" in line or re.search(r"#\[derive\([^]]*\bTS\b", line):
|
||||||
|
violations.append(
|
||||||
|
Violation(
|
||||||
|
"KH_TS002",
|
||||||
|
relative,
|
||||||
|
index,
|
||||||
|
"TS-RS derives/attributes belong to application DTO boundaries, not generic ks-* runtime types",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
for generated in [crate / "frontend/ts/bindings", crate / "bindings"]:
|
||||||
|
if generated.exists():
|
||||||
|
violations.append(
|
||||||
|
Violation(
|
||||||
|
"KH_TS003",
|
||||||
|
generated.relative_to(root).as_posix(),
|
||||||
|
1,
|
||||||
|
"generic ks-* crates must not own generated TypeScript bindings",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
desktop = root / "kb-app-demo-desktop/src"
|
||||||
|
if desktop.exists():
|
||||||
|
field_pattern = re.compile(r"^\s*pub\(crate\)\s+[A-Za-z0-9_]+:\s+ks_[a-z0-9_]+::")
|
||||||
|
for path in sorted(desktop.rglob("*.rs")):
|
||||||
|
relative = path.relative_to(root).as_posix()
|
||||||
|
for index, line in enumerate(path.read_text(encoding="utf-8").splitlines(), 1):
|
||||||
|
if field_pattern.search(line):
|
||||||
|
violations.append(
|
||||||
|
Violation(
|
||||||
|
"KH_TS004",
|
||||||
|
relative,
|
||||||
|
index,
|
||||||
|
"desktop DTO/state fields that cross application boundaries must use application-owned wrappers rather than direct ks-* field types",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
tauri_path = root / "kb-app-demo-desktop/src/tauri.rs"
|
||||||
|
if tauri_path.is_file():
|
||||||
|
lines = tauri_path.read_text(encoding="utf-8").splitlines()
|
||||||
|
for index, line in enumerate(lines):
|
||||||
|
if line.strip() != "#[tauri::command]":
|
||||||
|
continue
|
||||||
|
signature_lines: list[str] = []
|
||||||
|
for candidate in lines[index + 1 : index + 20]:
|
||||||
|
signature_lines.append(candidate)
|
||||||
|
if "{" in candidate:
|
||||||
|
break
|
||||||
|
signature = "\n".join(signature_lines)
|
||||||
|
if re.search(r"->[^\{]*\bks_[a-z0-9_]+::", signature, re.DOTALL):
|
||||||
|
violations.append(
|
||||||
|
Violation(
|
||||||
|
"KH_TS005",
|
||||||
|
"kb-app-demo-desktop/src/tauri.rs",
|
||||||
|
index + 1,
|
||||||
|
"Tauri command return types must use desktop-owned DTO wrappers instead of direct ks-* contracts",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return violations
|
||||||
|
|
||||||
|
def audit_sensitive_transport_surfaces(root: pathlib.Path) -> list[Violation]:
|
||||||
|
"""Keep resolved transport URLs and other internal paths away from public boundaries."""
|
||||||
|
|
||||||
|
violations: list[Violation] = []
|
||||||
|
protected = {
|
||||||
|
"ks-onchain-transport/src/http_client.rs": "HttpPoolClientSnapshot",
|
||||||
|
"ks-onchain-transport/src/ws_client.rs": "WsPoolClientSnapshot",
|
||||||
|
"ks-onchain-transport/src/ws_session.rs": "WsSessionSnapshot",
|
||||||
|
}
|
||||||
|
for relative, struct_name in protected.items():
|
||||||
|
path = root / relative
|
||||||
|
if not path.is_file():
|
||||||
|
continue
|
||||||
|
text = path.read_text(encoding="utf-8")
|
||||||
|
struct_match = re.search(
|
||||||
|
rf"pub struct {struct_name}\s*\{{(?P<body>.*?)\n\}}",
|
||||||
|
text,
|
||||||
|
re.DOTALL,
|
||||||
|
)
|
||||||
|
if struct_match is not None and re.search(r"\bendpoint_url\s*:", struct_match.group("body")):
|
||||||
|
violations.append(
|
||||||
|
Violation(
|
||||||
|
"KH_SEC001",
|
||||||
|
relative,
|
||||||
|
text[: struct_match.start()].count("\n") + 1,
|
||||||
|
f"backend snapshot `{struct_name}` must not retain a resolved endpoint URL",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
derive_match = re.search(
|
||||||
|
rf"#\[derive\(([^)]*)\)\]\s*(?:#\[[^\]]+\]\s*)*pub struct {struct_name}\b",
|
||||||
|
text,
|
||||||
|
re.DOTALL,
|
||||||
|
)
|
||||||
|
if derive_match is not None and "serde::Serialize" in derive_match.group(1):
|
||||||
|
violations.append(
|
||||||
|
Violation(
|
||||||
|
"KH_SEC002",
|
||||||
|
relative,
|
||||||
|
text[: derive_match.start()].count("\n") + 1,
|
||||||
|
f"backend transport snapshot `{struct_name}` must not derive Serialize",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
desktop_root = root / "kb-app-demo-desktop/src"
|
||||||
|
if desktop_root.is_dir():
|
||||||
|
forbidden_fields = {
|
||||||
|
"endpoint_url": "resolved endpoint URLs must not cross the Tauri boundary",
|
||||||
|
"fixture_path": "wallet-derived fixture paths must not cross functional Tauri payloads",
|
||||||
|
}
|
||||||
|
field_pattern = re.compile(r"pub\(crate\)\s+([a-z][a-z0-9_]*):")
|
||||||
|
for path in sorted(desktop_root.rglob("*.rs")):
|
||||||
|
relative = path.relative_to(root).as_posix()
|
||||||
|
for index, line in enumerate(path.read_text(encoding="utf-8").splitlines(), 1):
|
||||||
|
match = field_pattern.search(line)
|
||||||
|
if match is None or match.group(1) not in forbidden_fields:
|
||||||
|
continue
|
||||||
|
violations.append(
|
||||||
|
Violation(
|
||||||
|
"KH_SEC003",
|
||||||
|
relative,
|
||||||
|
index,
|
||||||
|
forbidden_fields[match.group(1)],
|
||||||
|
)
|
||||||
|
)
|
||||||
|
transport_root = root / "ks-onchain-transport/src"
|
||||||
|
if transport_root.is_dir():
|
||||||
|
forbidden_fragments = {
|
||||||
|
"rpc_error_message = %error_response.error.message": "remote JSON-RPC messages must not be copied into transport logs",
|
||||||
|
'.field("endpoint_url", &self.endpoint.url)': "transport Debug must not expose a resolved endpoint URL",
|
||||||
|
"pub fn endpoint_url(&self) -> &str": "resolved endpoint URL getters must remain crate-private",
|
||||||
|
}
|
||||||
|
for path in sorted(transport_root.rglob("*.rs")):
|
||||||
|
relative = path.relative_to(root).as_posix()
|
||||||
|
text = path.read_text(encoding="utf-8")
|
||||||
|
for fragment, message in forbidden_fragments.items():
|
||||||
|
start = 0
|
||||||
|
while True:
|
||||||
|
offset = text.find(fragment, start)
|
||||||
|
if offset < 0:
|
||||||
|
break
|
||||||
|
violations.append(
|
||||||
|
Violation(
|
||||||
|
"KH_SEC004",
|
||||||
|
relative,
|
||||||
|
text[:offset].count("\n") + 1,
|
||||||
|
message,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
start = offset + len(fragment)
|
||||||
|
concrete_api_key = re.compile(r"api-key=([0-9a-fA-F]{8,}(?:-[0-9a-fA-F]+)*)")
|
||||||
|
secret_scan_roots = [root / "config", root / "ks-config", root / "ks-logging", root / "ks-onchain-transport", root / "kb-app-demo-desktop"]
|
||||||
|
for scan_root in secret_scan_roots:
|
||||||
|
if not scan_root.is_dir():
|
||||||
|
continue
|
||||||
|
for path in sorted(scan_root.rglob("*")):
|
||||||
|
if not path.is_file() or "frontend/ts/bindings" in path.as_posix():
|
||||||
|
continue
|
||||||
|
if path.suffix not in {".rs", ".json", ".md", ".ts", ".html"}:
|
||||||
|
continue
|
||||||
|
text = path.read_text(encoding="utf-8", errors="ignore")
|
||||||
|
match = concrete_api_key.search(text)
|
||||||
|
if match is None:
|
||||||
|
continue
|
||||||
|
violations.append(
|
||||||
|
Violation(
|
||||||
|
"KH_SEC006",
|
||||||
|
path.relative_to(root).as_posix(),
|
||||||
|
text[: match.start()].count("\n") + 1,
|
||||||
|
"concrete API-key material is forbidden in active source, configuration, documentation and tests",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
http_client_path = root / "ks-onchain-transport/src/http_client.rs"
|
||||||
|
if http_client_path.is_file():
|
||||||
|
text = http_client_path.read_text(encoding="utf-8")
|
||||||
|
forbidden_http = [
|
||||||
|
"retry_index, text\n",
|
||||||
|
"error_response.error.message\n ))",
|
||||||
|
]
|
||||||
|
for fragment in forbidden_http:
|
||||||
|
offset = text.find(fragment)
|
||||||
|
if offset >= 0:
|
||||||
|
violations.append(
|
||||||
|
Violation(
|
||||||
|
"KH_SEC005",
|
||||||
|
"ks-onchain-transport/src/http_client.rs",
|
||||||
|
text[:offset].count("\n") + 1,
|
||||||
|
"HTTP transport errors must not copy remote response bodies or JSON-RPC messages",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return violations
|
||||||
|
|
||||||
def audit_wincode_resolution(root: pathlib.Path) -> list[Violation]:
|
def audit_wincode_resolution(root: pathlib.Path) -> list[Violation]:
|
||||||
"""Require the currently compatible Solana wincode dependency family."""
|
"""Require the currently compatible Solana wincode dependency family."""
|
||||||
|
|
||||||
@@ -1155,7 +1392,9 @@ def main() -> int:
|
|||||||
+audit_private_ks_lib_paths_in_active_docs(root)
|
+audit_private_ks_lib_paths_in_active_docs(root)
|
||||||
+audit_solana_types(root)
|
+audit_solana_types(root)
|
||||||
+audit_environment_namespaces(root)
|
+audit_environment_namespaces(root)
|
||||||
|
+audit_ts_rs_boundaries(root)
|
||||||
+audit_configuration_split(root)
|
+audit_configuration_split(root)
|
||||||
|
+audit_sensitive_transport_surfaces(root)
|
||||||
+audit_wincode_resolution(root)
|
+audit_wincode_resolution(root)
|
||||||
)
|
)
|
||||||
violations.sort(key=lambda item: (item.code, item.path, item.line, item.message))
|
violations.sort(key=lambda item: (item.code, item.path, item.line, item.message))
|
||||||
|
|||||||
@@ -3,10 +3,6 @@
|
|||||||
"profiles": [
|
"profiles": [
|
||||||
{
|
{
|
||||||
"name": "local_devnet",
|
"name": "local_devnet",
|
||||||
"app": {
|
|
||||||
"name": "khadhroony-bot3",
|
|
||||||
"environment": "development"
|
|
||||||
},
|
|
||||||
"database": {
|
"database": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"backend": "postgres",
|
"backend": "postgres",
|
||||||
@@ -225,10 +221,6 @@
|
|||||||
"devnet_send_enabled": true,
|
"devnet_send_enabled": true,
|
||||||
"testnet_send_enabled": false,
|
"testnet_send_enabled": false,
|
||||||
"mainnet_send_enabled": false
|
"mainnet_send_enabled": false
|
||||||
},
|
|
||||||
"demo": {
|
|
||||||
"live_demo_enabled": true,
|
|
||||||
"trading_demo_enabled": false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -3,10 +3,6 @@
|
|||||||
"profiles": [
|
"profiles": [
|
||||||
{
|
{
|
||||||
"name": "local_devnet",
|
"name": "local_devnet",
|
||||||
"app": {
|
|
||||||
"name": "khadhroony-bot3",
|
|
||||||
"environment": "development"
|
|
||||||
},
|
|
||||||
"database": {
|
"database": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"backend": "postgres",
|
"backend": "postgres",
|
||||||
@@ -225,18 +221,10 @@
|
|||||||
"devnet_send_enabled": true,
|
"devnet_send_enabled": true,
|
||||||
"testnet_send_enabled": false,
|
"testnet_send_enabled": false,
|
||||||
"mainnet_send_enabled": false
|
"mainnet_send_enabled": false
|
||||||
},
|
|
||||||
"demo": {
|
|
||||||
"live_demo_enabled": true,
|
|
||||||
"trading_demo_enabled": false
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "mainnet_research",
|
"name": "mainnet_research",
|
||||||
"app": {
|
|
||||||
"name": "khadhroony-bot3",
|
|
||||||
"environment": "research"
|
|
||||||
},
|
|
||||||
"database": {
|
"database": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"backend": "postgres",
|
"backend": "postgres",
|
||||||
@@ -655,18 +643,10 @@
|
|||||||
"devnet_send_enabled": false,
|
"devnet_send_enabled": false,
|
||||||
"testnet_send_enabled": false,
|
"testnet_send_enabled": false,
|
||||||
"mainnet_send_enabled": false
|
"mainnet_send_enabled": false
|
||||||
},
|
|
||||||
"demo": {
|
|
||||||
"live_demo_enabled": true,
|
|
||||||
"trading_demo_enabled": false
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "mainnet",
|
"name": "mainnet",
|
||||||
"app": {
|
|
||||||
"name": "khadhroony-bot3",
|
|
||||||
"environment": "mainnet"
|
|
||||||
},
|
|
||||||
"database": {
|
"database": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"backend": "postgres",
|
"backend": "postgres",
|
||||||
@@ -1085,10 +1065,6 @@
|
|||||||
"devnet_send_enabled": false,
|
"devnet_send_enabled": false,
|
||||||
"testnet_send_enabled": false,
|
"testnet_send_enabled": false,
|
||||||
"mainnet_send_enabled": false
|
"mainnet_send_enabled": false
|
||||||
},
|
|
||||||
"demo": {
|
|
||||||
"live_demo_enabled": true,
|
|
||||||
"trading_demo_enabled": false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
Reference in New Issue
Block a user