@enbox/agent 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser.js +2215 -0
- package/dist/browser.js.map +7 -0
- package/dist/browser.mjs +2215 -0
- package/dist/browser.mjs.map +7 -0
- package/dist/cjs/index.js +8530 -0
- package/dist/cjs/index.js.map +7 -0
- package/dist/cjs/package.json +1 -0
- package/dist/esm/agent-did-resolver-cache.js +87 -0
- package/dist/esm/agent-did-resolver-cache.js.map +1 -0
- package/dist/esm/bearer-identity.js +41 -0
- package/dist/esm/bearer-identity.js.map +1 -0
- package/dist/esm/connect.js +191 -0
- package/dist/esm/connect.js.map +1 -0
- package/dist/esm/crypto-api.js +346 -0
- package/dist/esm/crypto-api.js.map +1 -0
- package/dist/esm/did-api.js +278 -0
- package/dist/esm/did-api.js.map +1 -0
- package/dist/esm/dwn-api.js +336 -0
- package/dist/esm/dwn-api.js.map +1 -0
- package/dist/esm/dwn-registrar.js +120 -0
- package/dist/esm/dwn-registrar.js.map +1 -0
- package/dist/esm/hd-identity-vault.js +729 -0
- package/dist/esm/hd-identity-vault.js.map +1 -0
- package/dist/esm/identity-api.js +262 -0
- package/dist/esm/identity-api.js.map +1 -0
- package/dist/esm/index.js +23 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/local-key-manager.js +498 -0
- package/dist/esm/local-key-manager.js.map +1 -0
- package/dist/esm/oidc.js +507 -0
- package/dist/esm/oidc.js.map +1 -0
- package/dist/esm/permissions-api.js +322 -0
- package/dist/esm/permissions-api.js.map +1 -0
- package/dist/esm/prototyping/clients/dwn-rpc-types.js +2 -0
- package/dist/esm/prototyping/clients/dwn-rpc-types.js.map +1 -0
- package/dist/esm/prototyping/clients/dwn-server-info-cache-memory.js +74 -0
- package/dist/esm/prototyping/clients/dwn-server-info-cache-memory.js.map +1 -0
- package/dist/esm/prototyping/clients/http-dwn-rpc-client.js +105 -0
- package/dist/esm/prototyping/clients/http-dwn-rpc-client.js.map +1 -0
- package/dist/esm/prototyping/clients/json-rpc-socket.js +150 -0
- package/dist/esm/prototyping/clients/json-rpc-socket.js.map +1 -0
- package/dist/esm/prototyping/clients/json-rpc.js +58 -0
- package/dist/esm/prototyping/clients/json-rpc.js.map +1 -0
- package/dist/esm/prototyping/clients/server-info-types.js +2 -0
- package/dist/esm/prototyping/clients/server-info-types.js.map +1 -0
- package/dist/esm/prototyping/clients/web-socket-clients.js +90 -0
- package/dist/esm/prototyping/clients/web-socket-clients.js.map +1 -0
- package/dist/esm/prototyping/common/object.js +14 -0
- package/dist/esm/prototyping/common/object.js.map +1 -0
- package/dist/esm/prototyping/common/type-utils.js +2 -0
- package/dist/esm/prototyping/common/type-utils.js.map +1 -0
- package/dist/esm/prototyping/crypto/algorithms/aes-gcm.js +147 -0
- package/dist/esm/prototyping/crypto/algorithms/aes-gcm.js.map +1 -0
- package/dist/esm/prototyping/crypto/algorithms/aes-kw.js +137 -0
- package/dist/esm/prototyping/crypto/algorithms/aes-kw.js.map +1 -0
- package/dist/esm/prototyping/crypto/algorithms/ecdsa.js +307 -0
- package/dist/esm/prototyping/crypto/algorithms/ecdsa.js.map +1 -0
- package/dist/esm/prototyping/crypto/algorithms/eddsa.js +264 -0
- package/dist/esm/prototyping/crypto/algorithms/eddsa.js.map +1 -0
- package/dist/esm/prototyping/crypto/algorithms/hkdf.js +39 -0
- package/dist/esm/prototyping/crypto/algorithms/hkdf.js.map +1 -0
- package/dist/esm/prototyping/crypto/algorithms/pbkdf2.js +41 -0
- package/dist/esm/prototyping/crypto/algorithms/pbkdf2.js.map +1 -0
- package/dist/esm/prototyping/crypto/crypto-error.js +41 -0
- package/dist/esm/prototyping/crypto/crypto-error.js.map +1 -0
- package/dist/esm/prototyping/crypto/dsa.js +236 -0
- package/dist/esm/prototyping/crypto/dsa.js.map +1 -0
- package/dist/esm/prototyping/crypto/jose/jwe-compact.js +130 -0
- package/dist/esm/prototyping/crypto/jose/jwe-compact.js.map +1 -0
- package/dist/esm/prototyping/crypto/jose/jwe-flattened.js +294 -0
- package/dist/esm/prototyping/crypto/jose/jwe-flattened.js.map +1 -0
- package/dist/esm/prototyping/crypto/jose/jwe.js +308 -0
- package/dist/esm/prototyping/crypto/jose/jwe.js.map +1 -0
- package/dist/esm/prototyping/crypto/primitives/aes-gcm.js +352 -0
- package/dist/esm/prototyping/crypto/primitives/aes-gcm.js.map +1 -0
- package/dist/esm/prototyping/crypto/primitives/aes-kw.js +247 -0
- package/dist/esm/prototyping/crypto/primitives/aes-kw.js.map +1 -0
- package/dist/esm/prototyping/crypto/primitives/hkdf.js +80 -0
- package/dist/esm/prototyping/crypto/primitives/hkdf.js.map +1 -0
- package/dist/esm/prototyping/crypto/primitives/pbkdf2.js +85 -0
- package/dist/esm/prototyping/crypto/primitives/pbkdf2.js.map +1 -0
- package/dist/esm/prototyping/crypto/types/cipher.js +2 -0
- package/dist/esm/prototyping/crypto/types/cipher.js.map +1 -0
- package/dist/esm/prototyping/crypto/types/crypto-api.js +2 -0
- package/dist/esm/prototyping/crypto/types/crypto-api.js.map +1 -0
- package/dist/esm/prototyping/crypto/types/key-converter.js +2 -0
- package/dist/esm/prototyping/crypto/types/key-converter.js.map +1 -0
- package/dist/esm/prototyping/crypto/types/key-deriver.js +2 -0
- package/dist/esm/prototyping/crypto/types/key-deriver.js.map +1 -0
- package/dist/esm/prototyping/crypto/types/key-io.js +2 -0
- package/dist/esm/prototyping/crypto/types/key-io.js.map +1 -0
- package/dist/esm/prototyping/crypto/types/key-manager.js +2 -0
- package/dist/esm/prototyping/crypto/types/key-manager.js.map +1 -0
- package/dist/esm/prototyping/crypto/types/key-wrapper.js +2 -0
- package/dist/esm/prototyping/crypto/types/key-wrapper.js.map +1 -0
- package/dist/esm/prototyping/crypto/types/params-direct.js +2 -0
- package/dist/esm/prototyping/crypto/types/params-direct.js.map +1 -0
- package/dist/esm/prototyping/crypto/types/params-kms.js +2 -0
- package/dist/esm/prototyping/crypto/types/params-kms.js.map +1 -0
- package/dist/esm/prototyping/crypto/utils.js +19 -0
- package/dist/esm/prototyping/crypto/utils.js.map +1 -0
- package/dist/esm/prototyping/dids/resolver-cache-memory.js +77 -0
- package/dist/esm/prototyping/dids/resolver-cache-memory.js.map +1 -0
- package/dist/esm/prototyping/dids/utils.js +9 -0
- package/dist/esm/prototyping/dids/utils.js.map +1 -0
- package/dist/esm/rpc-client.js +123 -0
- package/dist/esm/rpc-client.js.map +1 -0
- package/dist/esm/store-data-protocols.js +38 -0
- package/dist/esm/store-data-protocols.js.map +1 -0
- package/dist/esm/store-data.js +320 -0
- package/dist/esm/store-data.js.map +1 -0
- package/dist/esm/store-did.js +136 -0
- package/dist/esm/store-did.js.map +1 -0
- package/dist/esm/store-identity.js +140 -0
- package/dist/esm/store-identity.js.map +1 -0
- package/dist/esm/store-key.js +136 -0
- package/dist/esm/store-key.js.map +1 -0
- package/dist/esm/sync-api.js +61 -0
- package/dist/esm/sync-api.js.map +1 -0
- package/dist/esm/sync-engine-level.js +618 -0
- package/dist/esm/sync-engine-level.js.map +1 -0
- package/dist/esm/test-harness.js +239 -0
- package/dist/esm/test-harness.js.map +1 -0
- package/dist/esm/types/agent.js +2 -0
- package/dist/esm/types/agent.js.map +1 -0
- package/dist/esm/types/dwn.js +31 -0
- package/dist/esm/types/dwn.js.map +1 -0
- package/dist/esm/types/identity-vault.js +2 -0
- package/dist/esm/types/identity-vault.js.map +1 -0
- package/dist/esm/types/identity.js +2 -0
- package/dist/esm/types/identity.js.map +1 -0
- package/dist/esm/types/key-manager.js +2 -0
- package/dist/esm/types/key-manager.js.map +1 -0
- package/dist/esm/types/permissions.js +2 -0
- package/dist/esm/types/permissions.js.map +1 -0
- package/dist/esm/types/sync.js +2 -0
- package/dist/esm/types/sync.js.map +1 -0
- package/dist/esm/types/vc.js +5 -0
- package/dist/esm/types/vc.js.map +1 -0
- package/dist/esm/utils-internal.js +147 -0
- package/dist/esm/utils-internal.js.map +1 -0
- package/dist/esm/utils.js +161 -0
- package/dist/esm/utils.js.map +1 -0
- package/dist/types/agent-did-resolver-cache.d.ts +30 -0
- package/dist/types/agent-did-resolver-cache.d.ts.map +1 -0
- package/dist/types/bearer-identity.d.ts +31 -0
- package/dist/types/bearer-identity.d.ts.map +1 -0
- package/dist/types/connect.d.ts +88 -0
- package/dist/types/connect.d.ts.map +1 -0
- package/dist/types/crypto-api.d.ts +286 -0
- package/dist/types/crypto-api.d.ts.map +1 -0
- package/dist/types/did-api.d.ts +119 -0
- package/dist/types/did-api.d.ts.map +1 -0
- package/dist/types/dwn-api.d.ts +66 -0
- package/dist/types/dwn-api.d.ts.map +1 -0
- package/dist/types/dwn-registrar.d.ts +29 -0
- package/dist/types/dwn-registrar.d.ts.map +1 -0
- package/dist/types/hd-identity-vault.d.ts +306 -0
- package/dist/types/hd-identity-vault.d.ts.map +1 -0
- package/dist/types/identity-api.d.ts +107 -0
- package/dist/types/identity-api.d.ts.map +1 -0
- package/dist/types/index.d.ts +30 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/local-key-manager.d.ts +311 -0
- package/dist/types/local-key-manager.d.ts.map +1 -0
- package/dist/types/oidc.d.ts +247 -0
- package/dist/types/oidc.d.ts.map +1 -0
- package/dist/types/permissions-api.d.ts +35 -0
- package/dist/types/permissions-api.d.ts.map +1 -0
- package/dist/types/prototyping/clients/dwn-rpc-types.d.ts +45 -0
- package/dist/types/prototyping/clients/dwn-rpc-types.d.ts.map +1 -0
- package/dist/types/prototyping/clients/dwn-server-info-cache-memory.d.ts +57 -0
- package/dist/types/prototyping/clients/dwn-server-info-cache-memory.d.ts.map +1 -0
- package/dist/types/prototyping/clients/http-dwn-rpc-client.d.ts +13 -0
- package/dist/types/prototyping/clients/http-dwn-rpc-client.d.ts.map +1 -0
- package/dist/types/prototyping/clients/json-rpc-socket.d.ts +43 -0
- package/dist/types/prototyping/clients/json-rpc-socket.d.ts.map +1 -0
- package/dist/types/prototyping/clients/json-rpc.d.ts +49 -0
- package/dist/types/prototyping/clients/json-rpc.d.ts.map +1 -0
- package/dist/types/prototyping/clients/server-info-types.d.ts +20 -0
- package/dist/types/prototyping/clients/server-info-types.d.ts.map +1 -0
- package/dist/types/prototyping/clients/web-socket-clients.d.ts +10 -0
- package/dist/types/prototyping/clients/web-socket-clients.d.ts.map +1 -0
- package/dist/types/prototyping/common/object.d.ts +2 -0
- package/dist/types/prototyping/common/object.d.ts.map +1 -0
- package/dist/types/prototyping/common/type-utils.d.ts +7 -0
- package/dist/types/prototyping/common/type-utils.d.ts.map +1 -0
- package/dist/types/prototyping/crypto/algorithms/aes-gcm.d.ts +151 -0
- package/dist/types/prototyping/crypto/algorithms/aes-gcm.d.ts.map +1 -0
- package/dist/types/prototyping/crypto/algorithms/aes-kw.d.ts +109 -0
- package/dist/types/prototyping/crypto/algorithms/aes-kw.d.ts.map +1 -0
- package/dist/types/prototyping/crypto/algorithms/ecdsa.d.ts +160 -0
- package/dist/types/prototyping/crypto/algorithms/ecdsa.d.ts.map +1 -0
- package/dist/types/prototyping/crypto/algorithms/eddsa.d.ts +157 -0
- package/dist/types/prototyping/crypto/algorithms/eddsa.d.ts.map +1 -0
- package/dist/types/prototyping/crypto/algorithms/hkdf.d.ts +21 -0
- package/dist/types/prototyping/crypto/algorithms/hkdf.d.ts.map +1 -0
- package/dist/types/prototyping/crypto/algorithms/pbkdf2.d.ts +21 -0
- package/dist/types/prototyping/crypto/algorithms/pbkdf2.d.ts.map +1 -0
- package/dist/types/prototyping/crypto/crypto-error.d.ts +29 -0
- package/dist/types/prototyping/crypto/crypto-error.d.ts.map +1 -0
- package/dist/types/prototyping/crypto/dsa.d.ts +169 -0
- package/dist/types/prototyping/crypto/dsa.d.ts.map +1 -0
- package/dist/types/prototyping/crypto/jose/jwe-compact.d.ts +135 -0
- package/dist/types/prototyping/crypto/jose/jwe-compact.d.ts.map +1 -0
- package/dist/types/prototyping/crypto/jose/jwe-flattened.d.ts +134 -0
- package/dist/types/prototyping/crypto/jose/jwe-flattened.d.ts.map +1 -0
- package/dist/types/prototyping/crypto/jose/jwe.d.ts +378 -0
- package/dist/types/prototyping/crypto/jose/jwe.d.ts.map +1 -0
- package/dist/types/prototyping/crypto/primitives/aes-gcm.d.ts +245 -0
- package/dist/types/prototyping/crypto/primitives/aes-gcm.d.ts.map +1 -0
- package/dist/types/prototyping/crypto/primitives/aes-kw.d.ts +103 -0
- package/dist/types/prototyping/crypto/primitives/aes-kw.d.ts.map +1 -0
- package/dist/types/prototyping/crypto/primitives/hkdf.d.ts +90 -0
- package/dist/types/prototyping/crypto/primitives/hkdf.d.ts.map +1 -0
- package/dist/types/prototyping/crypto/primitives/pbkdf2.d.ts +84 -0
- package/dist/types/prototyping/crypto/primitives/pbkdf2.d.ts.map +1 -0
- package/dist/types/prototyping/crypto/types/cipher.d.ts +14 -0
- package/dist/types/prototyping/crypto/types/cipher.d.ts.map +1 -0
- package/dist/types/prototyping/crypto/types/crypto-api.d.ts +35 -0
- package/dist/types/prototyping/crypto/types/crypto-api.d.ts.map +1 -0
- package/dist/types/prototyping/crypto/types/key-converter.d.ts +49 -0
- package/dist/types/prototyping/crypto/types/key-converter.d.ts.map +1 -0
- package/dist/types/prototyping/crypto/types/key-deriver.d.ts +50 -0
- package/dist/types/prototyping/crypto/types/key-deriver.d.ts.map +1 -0
- package/dist/types/prototyping/crypto/types/key-io.d.ts +49 -0
- package/dist/types/prototyping/crypto/types/key-io.d.ts.map +1 -0
- package/dist/types/prototyping/crypto/types/key-manager.d.ts +69 -0
- package/dist/types/prototyping/crypto/types/key-manager.d.ts.map +1 -0
- package/dist/types/prototyping/crypto/types/key-wrapper.d.ts +14 -0
- package/dist/types/prototyping/crypto/types/key-wrapper.d.ts.map +1 -0
- package/dist/types/prototyping/crypto/types/params-direct.d.ts +75 -0
- package/dist/types/prototyping/crypto/types/params-direct.d.ts.map +1 -0
- package/dist/types/prototyping/crypto/types/params-kms.d.ts +63 -0
- package/dist/types/prototyping/crypto/types/params-kms.d.ts.map +1 -0
- package/dist/types/prototyping/crypto/utils.d.ts +7 -0
- package/dist/types/prototyping/crypto/utils.d.ts.map +1 -0
- package/dist/types/prototyping/dids/resolver-cache-memory.d.ts +57 -0
- package/dist/types/prototyping/dids/resolver-cache-memory.d.ts.map +1 -0
- package/dist/types/prototyping/dids/utils.d.ts +3 -0
- package/dist/types/prototyping/dids/utils.d.ts.map +1 -0
- package/dist/types/rpc-client.d.ts +51 -0
- package/dist/types/rpc-client.d.ts.map +1 -0
- package/dist/types/store-data-protocols.d.ts +4 -0
- package/dist/types/store-data-protocols.d.ts.map +1 -0
- package/dist/types/store-data.d.ts +95 -0
- package/dist/types/store-data.d.ts.map +1 -0
- package/dist/types/store-did.d.ts +33 -0
- package/dist/types/store-did.d.ts.map +1 -0
- package/dist/types/store-identity.d.ts +34 -0
- package/dist/types/store-identity.d.ts.map +1 -0
- package/dist/types/store-key.d.ts +32 -0
- package/dist/types/store-key.d.ts.map +1 -0
- package/dist/types/sync-api.d.ts +41 -0
- package/dist/types/sync-api.d.ts.map +1 -0
- package/dist/types/sync-engine-level.d.ts +85 -0
- package/dist/types/sync-engine-level.d.ts.map +1 -0
- package/dist/types/test-harness.d.ts +69 -0
- package/dist/types/test-harness.d.ts.map +1 -0
- package/dist/types/types/agent.d.ts +172 -0
- package/dist/types/types/agent.d.ts.map +1 -0
- package/dist/types/types/dwn.d.ts +178 -0
- package/dist/types/types/dwn.d.ts.map +1 -0
- package/dist/types/types/identity-vault.d.ts +129 -0
- package/dist/types/types/identity-vault.d.ts.map +1 -0
- package/dist/types/types/identity.d.ts +16 -0
- package/dist/types/types/identity.d.ts.map +1 -0
- package/dist/types/types/key-manager.d.ts +9 -0
- package/dist/types/types/key-manager.d.ts.map +1 -0
- package/dist/types/types/permissions.d.ts +98 -0
- package/dist/types/types/permissions.d.ts.map +1 -0
- package/dist/types/types/sync.d.ts +66 -0
- package/dist/types/types/sync.d.ts.map +1 -0
- package/dist/types/types/vc.d.ts +7 -0
- package/dist/types/types/vc.d.ts.map +1 -0
- package/dist/types/utils-internal.d.ts +50 -0
- package/dist/types/utils-internal.d.ts.map +1 -0
- package/dist/types/utils.d.ts +37 -0
- package/dist/types/utils.d.ts.map +1 -0
- package/package.json +112 -0
- package/src/agent-did-resolver-cache.ts +95 -0
- package/src/bearer-identity.ts +42 -0
- package/src/connect.ts +296 -0
- package/src/crypto-api.ts +593 -0
- package/src/did-api.ts +429 -0
- package/src/dwn-api.ts +462 -0
- package/src/dwn-registrar.ts +127 -0
- package/src/hd-identity-vault.ts +853 -0
- package/src/identity-api.ts +324 -0
- package/src/index.ts +30 -0
- package/src/local-key-manager.ts +672 -0
- package/src/oidc.ts +857 -0
- package/src/permissions-api.ts +408 -0
- package/src/prototyping/clients/dwn-rpc-types.ts +55 -0
- package/src/prototyping/clients/dwn-server-info-cache-memory.ts +79 -0
- package/src/prototyping/clients/http-dwn-rpc-client.ts +110 -0
- package/src/prototyping/clients/json-rpc-socket.ts +169 -0
- package/src/prototyping/clients/json-rpc.ts +113 -0
- package/src/prototyping/clients/server-info-types.ts +21 -0
- package/src/prototyping/clients/web-socket-clients.ts +100 -0
- package/src/prototyping/common/object.ts +15 -0
- package/src/prototyping/common/type-utils.ts +6 -0
- package/src/prototyping/crypto/algorithms/aes-gcm.ts +211 -0
- package/src/prototyping/crypto/algorithms/aes-kw.ts +164 -0
- package/src/prototyping/crypto/algorithms/ecdsa.ts +365 -0
- package/src/prototyping/crypto/algorithms/eddsa.ts +310 -0
- package/src/prototyping/crypto/algorithms/hkdf.ts +40 -0
- package/src/prototyping/crypto/algorithms/pbkdf2.ts +44 -0
- package/src/prototyping/crypto/crypto-error.ts +45 -0
- package/src/prototyping/crypto/dsa.ts +367 -0
- package/src/prototyping/crypto/jose/jwe-compact.ts +225 -0
- package/src/prototyping/crypto/jose/jwe-flattened.ts +459 -0
- package/src/prototyping/crypto/jose/jwe.ts +653 -0
- package/src/prototyping/crypto/primitives/aes-gcm.ts +374 -0
- package/src/prototyping/crypto/primitives/aes-kw.ts +271 -0
- package/src/prototyping/crypto/primitives/hkdf.ts +121 -0
- package/src/prototyping/crypto/primitives/pbkdf2.ts +116 -0
- package/src/prototyping/crypto/types/cipher.ts +17 -0
- package/src/prototyping/crypto/types/crypto-api.ts +78 -0
- package/src/prototyping/crypto/types/key-converter.ts +53 -0
- package/src/prototyping/crypto/types/key-deriver.ts +56 -0
- package/src/prototyping/crypto/types/key-io.ts +51 -0
- package/src/prototyping/crypto/types/key-manager.ts +83 -0
- package/src/prototyping/crypto/types/key-wrapper.ts +17 -0
- package/src/prototyping/crypto/types/params-direct.ts +95 -0
- package/src/prototyping/crypto/types/params-kms.ts +76 -0
- package/src/prototyping/crypto/utils.ts +41 -0
- package/src/prototyping/dids/resolver-cache-memory.ts +83 -0
- package/src/prototyping/dids/utils.ts +10 -0
- package/src/rpc-client.ts +162 -0
- package/src/store-data-protocols.ts +40 -0
- package/src/store-data.ts +400 -0
- package/src/store-did.ts +105 -0
- package/src/store-identity.ts +109 -0
- package/src/store-key.ts +104 -0
- package/src/sync-api.ts +71 -0
- package/src/sync-engine-level.ts +714 -0
- package/src/test-harness.ts +330 -0
- package/src/types/agent.ts +195 -0
- package/src/types/dwn.ts +278 -0
- package/src/types/identity-vault.ts +137 -0
- package/src/types/identity.ts +18 -0
- package/src/types/key-manager.ts +15 -0
- package/src/types/permissions.ts +115 -0
- package/src/types/sync.ts +58 -0
- package/src/types/vc.ts +7 -0
- package/src/utils-internal.ts +157 -0
- package/src/utils.ts +181 -0
package/src/dwn-api.ts
ADDED
|
@@ -0,0 +1,462 @@
|
|
|
1
|
+
import type { Readable } from '@enbox/common';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
Cid,
|
|
5
|
+
DataStoreLevel,
|
|
6
|
+
Dwn,
|
|
7
|
+
DwnConfig,
|
|
8
|
+
DwnInterfaceName,
|
|
9
|
+
DwnMethodName,
|
|
10
|
+
EventEmitterStream,
|
|
11
|
+
EventLogLevel,
|
|
12
|
+
GenericMessage,
|
|
13
|
+
Message,
|
|
14
|
+
MessageStoreLevel,
|
|
15
|
+
ResumableTaskStoreLevel
|
|
16
|
+
} from '@enbox/dwn-sdk-js';
|
|
17
|
+
|
|
18
|
+
import { NodeStream } from '@enbox/common';
|
|
19
|
+
import { CryptoUtils } from '@enbox/crypto';
|
|
20
|
+
import { DidDht, DidJwk, DidResolverCacheLevel, UniversalResolver } from '@enbox/dids';
|
|
21
|
+
|
|
22
|
+
import type { Web5PlatformAgent } from './types/agent.js';
|
|
23
|
+
import type {
|
|
24
|
+
DwnMessage,
|
|
25
|
+
DwnMessageInstance,
|
|
26
|
+
DwnMessageParams,
|
|
27
|
+
DwnMessageReply,
|
|
28
|
+
DwnMessagesPermissionScope,
|
|
29
|
+
DwnMessageWithData,
|
|
30
|
+
DwnPermissionScope,
|
|
31
|
+
DwnRecordsInterfaces,
|
|
32
|
+
DwnRecordsPermissionScope,
|
|
33
|
+
DwnResponse,
|
|
34
|
+
DwnSigner,
|
|
35
|
+
MessageHandler,
|
|
36
|
+
ProcessDwnRequest,
|
|
37
|
+
SendDwnRequest
|
|
38
|
+
} from './types/dwn.js';
|
|
39
|
+
|
|
40
|
+
import { DwnInterface, dwnMessageConstructors } from './types/dwn.js';
|
|
41
|
+
import { blobToIsomorphicNodeReadable, getDwnServiceEndpointUrls, isRecordsWrite, webReadableToIsomorphicNodeReadable } from './utils.js';
|
|
42
|
+
|
|
43
|
+
export type DwnMessageWithBlob<T extends DwnInterface> = {
|
|
44
|
+
message: DwnMessage[T];
|
|
45
|
+
data?: Blob;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export type DwnApiParams = {
|
|
49
|
+
agent?: Web5PlatformAgent;
|
|
50
|
+
dwn: Dwn;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export interface DwnApiCreateDwnParams extends Partial<DwnConfig> {
|
|
54
|
+
dataPath?: string;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function isDwnRequest<T extends DwnInterface>(
|
|
58
|
+
dwnRequest: ProcessDwnRequest<DwnInterface>, messageType: T
|
|
59
|
+
): dwnRequest is ProcessDwnRequest<T> {
|
|
60
|
+
return dwnRequest.messageType === messageType;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function isDwnMessage<T extends DwnInterface>(
|
|
64
|
+
messageType: T, message: GenericMessage
|
|
65
|
+
): message is DwnMessage[T] {
|
|
66
|
+
const incomingMessageInterfaceName = message.descriptor.interface + message.descriptor.method;
|
|
67
|
+
return incomingMessageInterfaceName === messageType;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export function isRecordsType(messageType: DwnInterface): messageType is DwnRecordsInterfaces {
|
|
71
|
+
return messageType === DwnInterface.RecordsDelete ||
|
|
72
|
+
messageType === DwnInterface.RecordsQuery ||
|
|
73
|
+
messageType === DwnInterface.RecordsRead ||
|
|
74
|
+
messageType === DwnInterface.RecordsSubscribe ||
|
|
75
|
+
messageType === DwnInterface.RecordsWrite;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export function isRecordPermissionScope(scope: DwnPermissionScope): scope is DwnRecordsPermissionScope {
|
|
79
|
+
return scope.interface === DwnInterfaceName.Records;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export function isMessagesPermissionScope(scope: DwnPermissionScope): scope is DwnMessagesPermissionScope {
|
|
83
|
+
return scope.interface === DwnInterfaceName.Messages;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export class AgentDwnApi {
|
|
87
|
+
/**
|
|
88
|
+
* Holds the instance of a `Web5PlatformAgent` that represents the current execution context for
|
|
89
|
+
* the `AgentDwnApi`. This agent is used to interact with other Web5 agent components. It's vital
|
|
90
|
+
* to ensure this instance is set to correctly contextualize operations within the broader Web5
|
|
91
|
+
* Agent framework.
|
|
92
|
+
*/
|
|
93
|
+
private _agent?: Web5PlatformAgent;
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* The DWN instance to use for this API.
|
|
97
|
+
*/
|
|
98
|
+
private _dwn: Dwn;
|
|
99
|
+
|
|
100
|
+
constructor({ agent, dwn }: DwnApiParams) {
|
|
101
|
+
// If an agent is provided, set it as the execution context for this API.
|
|
102
|
+
this._agent = agent;
|
|
103
|
+
|
|
104
|
+
// Set the DWN instance for this API.
|
|
105
|
+
this._dwn = dwn;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Retrieves the `Web5PlatformAgent` execution context.
|
|
110
|
+
*
|
|
111
|
+
* @returns The `Web5PlatformAgent` instance that represents the current execution context.
|
|
112
|
+
* @throws Will throw an error if the `agent` instance property is undefined.
|
|
113
|
+
*/
|
|
114
|
+
get agent(): Web5PlatformAgent {
|
|
115
|
+
if (this._agent === undefined) {
|
|
116
|
+
throw new Error('AgentDwnApi: Unable to determine agent execution context.');
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return this._agent;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
set agent(agent: Web5PlatformAgent) {
|
|
123
|
+
this._agent = agent;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Public getter for the DWN instance used by this API.
|
|
128
|
+
*
|
|
129
|
+
* Notes:
|
|
130
|
+
* - This getter is public to allow advanced developers to access the DWN instance directly.
|
|
131
|
+
* However, it is recommended to use the `processRequest` method to interact with the DWN
|
|
132
|
+
* instance to ensure that the DWN message is constructed correctly.
|
|
133
|
+
* - The getter is named `node` to avoid confusion with the `dwn` property of the
|
|
134
|
+
* `Web5PlatformAgent`. In other words, so that a developer can call `agent.dwn.node` to access
|
|
135
|
+
* the DWN instance and not `agent.dwn.dwn`.
|
|
136
|
+
*/
|
|
137
|
+
get node(): Dwn {
|
|
138
|
+
return this._dwn;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
public static async createDwn({
|
|
142
|
+
dataPath, dataStore, didResolver, eventLog, eventStream, messageStore, tenantGate, resumableTaskStore
|
|
143
|
+
}: DwnApiCreateDwnParams): Promise<Dwn> {
|
|
144
|
+
dataStore ??= new DataStoreLevel({ blockstoreLocation: `${dataPath}/DWN_DATASTORE` });
|
|
145
|
+
|
|
146
|
+
didResolver ??= new UniversalResolver({
|
|
147
|
+
didResolvers : [DidDht, DidJwk],
|
|
148
|
+
cache : new DidResolverCacheLevel({ location: `${dataPath}/DID_RESOLVERCACHE` }),
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
eventLog ??= new EventLogLevel({ location: `${dataPath}/DWN_EVENTLOG` });
|
|
152
|
+
|
|
153
|
+
messageStore ??= new MessageStoreLevel(({
|
|
154
|
+
blockstoreLocation : `${dataPath}/DWN_MESSAGESTORE`,
|
|
155
|
+
indexLocation : `${dataPath}/DWN_MESSAGEINDEX`
|
|
156
|
+
}));
|
|
157
|
+
|
|
158
|
+
resumableTaskStore ??= new ResumableTaskStoreLevel({ location: `${dataPath}/DWN_RESUMABLETASKSTORE` });
|
|
159
|
+
|
|
160
|
+
eventStream ??= new EventEmitterStream();
|
|
161
|
+
|
|
162
|
+
return await Dwn.create({ dataStore, didResolver, eventLog, eventStream, messageStore, tenantGate, resumableTaskStore });
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
public async processRequest<T extends DwnInterface>(
|
|
166
|
+
request: ProcessDwnRequest<T>
|
|
167
|
+
): Promise<DwnResponse<T>> {
|
|
168
|
+
// Constructs a DWN message. and if there is a data payload, transforms the data to a Node
|
|
169
|
+
// Readable stream.
|
|
170
|
+
const { message, dataStream } = await this.constructDwnMessage({ request });
|
|
171
|
+
|
|
172
|
+
// Extracts the optional subscription handler from the request to pass into `processMessage.
|
|
173
|
+
const { subscriptionHandler } = request;
|
|
174
|
+
|
|
175
|
+
// Conditionally processes the message with the DWN instance:
|
|
176
|
+
// - If `store` is not explicitly set to false, it sends the message to the DWN node for
|
|
177
|
+
// processing, passing along the target DID, the message, and any associated data stream.
|
|
178
|
+
// - If `store` is set to false, it immediately returns a simulated 'accepted' status without
|
|
179
|
+
// storing the message/data in the DWN node.
|
|
180
|
+
const reply: DwnMessageReply[T] = (request.store !== false)
|
|
181
|
+
? await this._dwn.processMessage(request.target, message, { dataStream: dataStream as any, subscriptionHandler })
|
|
182
|
+
: { status: { code: 202, detail: 'Accepted' } };
|
|
183
|
+
|
|
184
|
+
// Returns an object containing the reply from processing the message, the original message,
|
|
185
|
+
// and the content identifier (CID) of the message.
|
|
186
|
+
return {
|
|
187
|
+
reply,
|
|
188
|
+
message,
|
|
189
|
+
messageCid: await Message.getCid(message),
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
public async sendRequest<T extends DwnInterface>(
|
|
194
|
+
request: SendDwnRequest<T>
|
|
195
|
+
): Promise<DwnResponse<T>> {
|
|
196
|
+
// First, confirm the target DID can be dereferenced and extract the DWN service endpoint URLs.
|
|
197
|
+
const dwnEndpointUrls = await getDwnServiceEndpointUrls(request.target, this.agent.did);
|
|
198
|
+
if (dwnEndpointUrls.length === 0) {
|
|
199
|
+
throw new Error(`AgentDwnApi: DID Service is missing or malformed: ${request.target}#dwn`);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
let messageCid: string | undefined;
|
|
203
|
+
let message: DwnMessage[T];
|
|
204
|
+
let data: Blob | undefined;
|
|
205
|
+
let subscriptionHandler: MessageHandler[T] | undefined;
|
|
206
|
+
|
|
207
|
+
// If `messageCid` is given, retrieve message and data, if any.
|
|
208
|
+
if ('messageCid' in request) {
|
|
209
|
+
({ message, data } = await this.getDwnMessage({
|
|
210
|
+
author : request.author,
|
|
211
|
+
messageCid : request.messageCid,
|
|
212
|
+
messageType : request.messageType
|
|
213
|
+
}));
|
|
214
|
+
messageCid = request.messageCid;
|
|
215
|
+
|
|
216
|
+
} else {
|
|
217
|
+
// Otherwise, construct a new message.
|
|
218
|
+
({ message } = await this.constructDwnMessage({ request }));
|
|
219
|
+
if (request.dataStream && !(request.dataStream instanceof Blob)) {
|
|
220
|
+
throw new Error('AgentDwnApi: DataStream must be provided as a Blob');
|
|
221
|
+
}
|
|
222
|
+
data = request.dataStream;
|
|
223
|
+
subscriptionHandler = request.subscriptionHandler;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// Send the RPC request to the target DID's DWN service endpoint using the Agent's RPC client.
|
|
227
|
+
const reply = await this.sendDwnRpcRequest({
|
|
228
|
+
targetDid: request.target,
|
|
229
|
+
dwnEndpointUrls,
|
|
230
|
+
message,
|
|
231
|
+
data,
|
|
232
|
+
subscriptionHandler
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
// If the message CID was not given in the `request`, compute it.
|
|
236
|
+
messageCid ??= await Message.getCid(message);
|
|
237
|
+
|
|
238
|
+
// Returns an object containing the reply from processing the message, the original message,
|
|
239
|
+
// and the content identifier (CID) of the message.
|
|
240
|
+
return { reply, message, messageCid };
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
private async sendDwnRpcRequest<T extends DwnInterface>({
|
|
244
|
+
targetDid, dwnEndpointUrls, message, data, subscriptionHandler
|
|
245
|
+
}: {
|
|
246
|
+
targetDid: string;
|
|
247
|
+
dwnEndpointUrls: string[];
|
|
248
|
+
message: DwnMessage[T];
|
|
249
|
+
data?: Blob;
|
|
250
|
+
subscriptionHandler?: MessageHandler[T];
|
|
251
|
+
}
|
|
252
|
+
): Promise<DwnMessageReply[T]> {
|
|
253
|
+
const errorMessages: { url: string, message: string }[] = [];
|
|
254
|
+
|
|
255
|
+
if (message.descriptor.method === DwnMethodName.Subscribe && subscriptionHandler === undefined) {
|
|
256
|
+
throw new Error('AgentDwnApi: Subscription handler is required for subscription requests.');
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// Try sending to author's publicly addressable DWNs until the first request succeeds.
|
|
260
|
+
for (let dwnUrl of dwnEndpointUrls) {
|
|
261
|
+
try {
|
|
262
|
+
if (subscriptionHandler !== undefined) {
|
|
263
|
+
// we get the server info to check if the server supports WebSocket for subscription requests
|
|
264
|
+
const serverInfo = await this.agent.rpc.getServerInfo(dwnUrl);
|
|
265
|
+
if (!serverInfo.webSocketSupport) {
|
|
266
|
+
// If the server does not support WebSocket, add an error message and continue to the next URL.
|
|
267
|
+
errorMessages.push({
|
|
268
|
+
url : dwnUrl,
|
|
269
|
+
message : 'WebSocket support is not enabled on the server.'
|
|
270
|
+
});
|
|
271
|
+
continue;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// If the server supports WebSocket, replace the subscription URL with a socket transport.
|
|
275
|
+
// For `http` we use the unsecured `ws` protocol, and for `https` we use the secured `wss` protocol.
|
|
276
|
+
const parsedUrl = new URL(dwnUrl);
|
|
277
|
+
parsedUrl.protocol = parsedUrl.protocol === 'http:' ? 'ws:' : 'wss:';
|
|
278
|
+
dwnUrl = parsedUrl.toString();
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
const dwnReply = await this.agent.rpc.sendDwnRequest({
|
|
282
|
+
dwnUrl,
|
|
283
|
+
targetDid,
|
|
284
|
+
message,
|
|
285
|
+
data,
|
|
286
|
+
subscriptionHandler
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
return dwnReply;
|
|
290
|
+
} catch(error: any) {
|
|
291
|
+
errorMessages.push({
|
|
292
|
+
url : dwnUrl,
|
|
293
|
+
message : (error instanceof Error) ? error.message : 'Unknown error',
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
throw new Error(`Failed to send DWN RPC request: ${JSON.stringify(errorMessages)}`);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
private async constructDwnMessage<T extends DwnInterface>({ request }: {
|
|
302
|
+
request: ProcessDwnRequest<T>
|
|
303
|
+
}): Promise<DwnMessageWithData<T>> {
|
|
304
|
+
// if the request has a granteeDid, ensure the messageParams include the proper grant parameters
|
|
305
|
+
if (request.granteeDid && !this.hasGrantParams(request.messageParams)) {
|
|
306
|
+
throw new Error('AgentDwnApi: Requested to sign with a permission but no grant messageParams were provided in the request');
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
const rawMessage = request.rawMessage;
|
|
310
|
+
let readableStream: Readable | undefined;
|
|
311
|
+
// TODO: Consider refactoring to move data transformations imposed by fetch() limitations to the HTTP transport-related methods.
|
|
312
|
+
// if the request is a RecordsWrite message, we need to handle the data stream and update the messageParams accordingly
|
|
313
|
+
if (isDwnRequest(request, DwnInterface.RecordsWrite)) {
|
|
314
|
+
const messageParams = request.messageParams;
|
|
315
|
+
|
|
316
|
+
if (request.dataStream && !messageParams?.data) {
|
|
317
|
+
const { dataStream } = request;
|
|
318
|
+
let isomorphicNodeReadable: Readable;
|
|
319
|
+
|
|
320
|
+
if (dataStream instanceof Blob) {
|
|
321
|
+
isomorphicNodeReadable = blobToIsomorphicNodeReadable(dataStream);
|
|
322
|
+
readableStream = blobToIsomorphicNodeReadable(dataStream);
|
|
323
|
+
|
|
324
|
+
} else if (dataStream instanceof ReadableStream) {
|
|
325
|
+
const [ forCid, forProcessMessage ] = dataStream.tee();
|
|
326
|
+
isomorphicNodeReadable = webReadableToIsomorphicNodeReadable(forCid);
|
|
327
|
+
readableStream = webReadableToIsomorphicNodeReadable(forProcessMessage);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
if (!rawMessage) {
|
|
331
|
+
// @ts-ignore
|
|
332
|
+
messageParams.dataCid = await Cid.computeDagPbCidFromStream(isomorphicNodeReadable);
|
|
333
|
+
// @ts-ignore
|
|
334
|
+
messageParams.dataSize ??= isomorphicNodeReadable['bytesRead'];
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
let dwnMessage: DwnMessageInstance[T];
|
|
340
|
+
const dwnMessageConstructor = dwnMessageConstructors[request.messageType];
|
|
341
|
+
|
|
342
|
+
// if there is no raw message provided, we need to create the dwn message
|
|
343
|
+
if (!rawMessage) {
|
|
344
|
+
|
|
345
|
+
// If we need to sign as an author delegate or with permissions we need to get the grantee's signer
|
|
346
|
+
// The messageParams should include either a permissionGrantId, or a delegatedGrant message
|
|
347
|
+
const signer = request.granteeDid ?
|
|
348
|
+
await this.getSigner(request.granteeDid) :
|
|
349
|
+
await this.getSigner(request.author);
|
|
350
|
+
|
|
351
|
+
dwnMessage = await dwnMessageConstructor.create({
|
|
352
|
+
// TODO: Implement alternative to type assertion.
|
|
353
|
+
...request.messageParams!,
|
|
354
|
+
signer
|
|
355
|
+
});
|
|
356
|
+
|
|
357
|
+
} else {
|
|
358
|
+
dwnMessage = await dwnMessageConstructor.parse(rawMessage);
|
|
359
|
+
if (isRecordsWrite(dwnMessage) && request.signAsOwner) {
|
|
360
|
+
// if we are signing as owner, we use the author's signer
|
|
361
|
+
const signer = await this.getSigner(request.author);
|
|
362
|
+
await dwnMessage.signAsOwner(signer);
|
|
363
|
+
} else if (request.granteeDid && isRecordsWrite(dwnMessage) && request.signAsOwnerDelegate) {
|
|
364
|
+
// if we are signing as owner delegate, we use the grantee's signer and the provided delegated grant
|
|
365
|
+
const signer = await this.getSigner(request.granteeDid);
|
|
366
|
+
|
|
367
|
+
//if we have reached here, the presence of the grant params has already been checked
|
|
368
|
+
const messageParams = request.messageParams as DwnMessageParams[DwnInterface.RecordsWrite];
|
|
369
|
+
await dwnMessage.signAsOwnerDelegate(signer, messageParams.delegatedGrant!);
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
return { message: dwnMessage.message as DwnMessage[T], dataStream: readableStream };
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
private hasGrantParams<T extends DwnInterface>(params?: DwnMessageParams[T]): boolean {
|
|
377
|
+
return params !== undefined &&
|
|
378
|
+
(('permissionGrantId' in params && params.permissionGrantId !== undefined) ||
|
|
379
|
+
('delegatedGrant' in params && params.delegatedGrant !== undefined));
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
private async getSigner(author: string): Promise<DwnSigner> {
|
|
383
|
+
// If the author is the Agent's DID, use the Agent's signer.
|
|
384
|
+
if (author === this.agent.agentDid.uri) {
|
|
385
|
+
const signer = await this.agent.agentDid.getSigner();
|
|
386
|
+
|
|
387
|
+
return {
|
|
388
|
+
algorithm : signer.algorithm,
|
|
389
|
+
keyId : signer.keyId,
|
|
390
|
+
sign : async (data: Uint8Array) => {
|
|
391
|
+
return await signer.sign({ data });
|
|
392
|
+
}
|
|
393
|
+
};
|
|
394
|
+
|
|
395
|
+
} else {
|
|
396
|
+
// Otherwise, use the author's DID to determine the signing method.
|
|
397
|
+
try {
|
|
398
|
+
const signingMethod = await this.agent.did.getSigningMethod({ didUri: author });
|
|
399
|
+
|
|
400
|
+
if (!signingMethod.publicKeyJwk) {
|
|
401
|
+
throw new Error(`Verification method '${signingMethod.id}' does not contain a public key in JWK format`);
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
// Compute the key URI of the verification method's public key.
|
|
405
|
+
const keyUri = await this.agent.keyManager.getKeyUri({ key: signingMethod.publicKeyJwk });
|
|
406
|
+
|
|
407
|
+
// Verify that the key is present in the key manager. If not, an error is thrown.
|
|
408
|
+
const publicKey = await this.agent.keyManager.getPublicKey({ keyUri });
|
|
409
|
+
|
|
410
|
+
// Bind the Agent's Key Manager to the signer.
|
|
411
|
+
const keyManager = this.agent.keyManager;
|
|
412
|
+
|
|
413
|
+
return {
|
|
414
|
+
algorithm : CryptoUtils.getJoseSignatureAlgorithmFromPublicKey(publicKey),
|
|
415
|
+
keyId : signingMethod.id,
|
|
416
|
+
sign : async (data: Uint8Array) => {
|
|
417
|
+
return await keyManager.sign({ data, keyUri: keyUri! });
|
|
418
|
+
}
|
|
419
|
+
};
|
|
420
|
+
} catch (error: any) {
|
|
421
|
+
throw new Error(`AgentDwnApi: Unable to get signer for author '${author}': ${error.message}`);
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
/**
|
|
427
|
+
* FURTHER REFACTORING NEEDED BELOW THIS LINE
|
|
428
|
+
*/
|
|
429
|
+
|
|
430
|
+
private async getDwnMessage<T extends DwnInterface>({ author, messageCid }: {
|
|
431
|
+
author: string;
|
|
432
|
+
messageType: T;
|
|
433
|
+
messageCid: string;
|
|
434
|
+
}): Promise<DwnMessageWithBlob<T>> {
|
|
435
|
+
const signer = await this.getSigner(author);
|
|
436
|
+
|
|
437
|
+
// Construct a MessagesRead message to fetch the message.
|
|
438
|
+
const messagesRead = await dwnMessageConstructors[DwnInterface.MessagesRead].create({
|
|
439
|
+
messageCid: messageCid,
|
|
440
|
+
signer
|
|
441
|
+
});
|
|
442
|
+
|
|
443
|
+
const result = await this._dwn.processMessage(author, messagesRead.message);
|
|
444
|
+
|
|
445
|
+
if (result.status.code !== 200) {
|
|
446
|
+
throw new Error(`AgentDwnApi: Failed to read message, response status: ${result.status.code} - ${result.status.detail}`);
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
const messageEntry = result.entry!;
|
|
450
|
+
const message = messageEntry.message as DwnMessage[T];
|
|
451
|
+
|
|
452
|
+
let dwnMessageWithBlob: DwnMessageWithBlob<T> = { message };
|
|
453
|
+
// If the message is a RecordsWrite, data will be present in the form of a stream
|
|
454
|
+
|
|
455
|
+
if (isRecordsWrite(messageEntry) && messageEntry.data) {
|
|
456
|
+
const dataBytes = await NodeStream.consumeToBytes({ readable: messageEntry.data });
|
|
457
|
+
dwnMessageWithBlob.data = new Blob([ dataBytes ], { type: messageEntry.message.descriptor.dataFormat });
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
return dwnMessageWithBlob;
|
|
461
|
+
}
|
|
462
|
+
}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { Sha256, CryptoUtils } from '@enbox/crypto';
|
|
2
|
+
import { concatenateUrl } from './utils.js';
|
|
3
|
+
import { Convert } from '@enbox/common';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* A client for registering tenants with a DWN.
|
|
7
|
+
*/
|
|
8
|
+
export class DwnRegistrar {
|
|
9
|
+
/**
|
|
10
|
+
* Registers a new tenant with the given DWN.
|
|
11
|
+
* NOTE: Assumes the user has already accepted the terms of service.
|
|
12
|
+
* NOTE: Currently the DWN Server from `dwn-server` does not require user signature.
|
|
13
|
+
* TODO: bring in types from `dwn-server`.
|
|
14
|
+
*/
|
|
15
|
+
public static async registerTenant(dwnEndpoint: string, did: string): Promise<void> {
|
|
16
|
+
|
|
17
|
+
const registrationEndpoint = concatenateUrl(dwnEndpoint, 'registration');
|
|
18
|
+
const termsOfUseEndpoint = concatenateUrl(registrationEndpoint, 'terms-of-service');
|
|
19
|
+
const proofOfWorkEndpoint = concatenateUrl(registrationEndpoint, 'proof-of-work');
|
|
20
|
+
|
|
21
|
+
// fetch the terms-of-service
|
|
22
|
+
const termsOfServiceGetResponse = await fetch(termsOfUseEndpoint, {
|
|
23
|
+
method: 'GET',
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
if (termsOfServiceGetResponse.status !== 200) {
|
|
27
|
+
const statusCode = termsOfServiceGetResponse.status;
|
|
28
|
+
const statusText = termsOfServiceGetResponse.statusText;
|
|
29
|
+
const errorText = await termsOfServiceGetResponse.text();
|
|
30
|
+
throw new Error(`Failed fetching terms-of-service: ${statusCode} ${statusText}: ${errorText}`);
|
|
31
|
+
}
|
|
32
|
+
const termsOfServiceFetched = await termsOfServiceGetResponse.text();
|
|
33
|
+
|
|
34
|
+
// fetch the proof-of-work challenge
|
|
35
|
+
const proofOfWorkChallengeGetResponse = await fetch(proofOfWorkEndpoint, {
|
|
36
|
+
method: 'GET',
|
|
37
|
+
});
|
|
38
|
+
const { challengeNonce, maximumAllowedHashValue} = await proofOfWorkChallengeGetResponse.json();
|
|
39
|
+
|
|
40
|
+
// create registration data based on the hash of the terms-of-service and the DID
|
|
41
|
+
const registrationData = {
|
|
42
|
+
did,
|
|
43
|
+
termsOfServiceHash: await DwnRegistrar.hashAsHexString(termsOfServiceFetched),
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
// compute the proof-of-work response nonce based on the the proof-of-work challenge and the registration data.
|
|
47
|
+
const responseNonce = await DwnRegistrar.findQualifiedResponseNonce({
|
|
48
|
+
challengeNonce,
|
|
49
|
+
maximumAllowedHashValue,
|
|
50
|
+
requestData: JSON.stringify(registrationData),
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
// send the registration request to the server
|
|
54
|
+
const registrationRequest = {
|
|
55
|
+
registrationData,
|
|
56
|
+
proofOfWork: {
|
|
57
|
+
challengeNonce,
|
|
58
|
+
responseNonce,
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
const registrationResponse = await fetch(registrationEndpoint, {
|
|
63
|
+
method : 'POST',
|
|
64
|
+
headers : { 'Content-Type': 'application/json' },
|
|
65
|
+
body : JSON.stringify(registrationRequest),
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
if (registrationResponse.status !== 200) {
|
|
69
|
+
const statusCode = registrationResponse.status;
|
|
70
|
+
const statusText = registrationResponse.statusText;
|
|
71
|
+
const errorText = await registrationResponse.text();
|
|
72
|
+
throw new Error(`Registration failed: ${statusCode} ${statusText}: ${errorText}`);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Computes the SHA-256 hash of the given array of strings.
|
|
78
|
+
*/
|
|
79
|
+
public static async hashAsHexString(input: string): Promise<string> {
|
|
80
|
+
const hashAsBytes = await Sha256.digest({ data: Convert.string(input).toUint8Array()});
|
|
81
|
+
const hashAsHex = Convert.uint8Array(hashAsBytes).toHex();
|
|
82
|
+
return hashAsHex;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Finds a response nonce that qualifies the difficulty requirement for the given proof-of-work challenge and request data.
|
|
87
|
+
*/
|
|
88
|
+
public static async findQualifiedResponseNonce(input: {
|
|
89
|
+
maximumAllowedHashValue: string;
|
|
90
|
+
challengeNonce: string;
|
|
91
|
+
requestData: string;
|
|
92
|
+
}): Promise<string> {
|
|
93
|
+
const startTime = Date.now();
|
|
94
|
+
|
|
95
|
+
const { maximumAllowedHashValue, challengeNonce, requestData } = input;
|
|
96
|
+
const maximumAllowedHashValueAsBigInt = BigInt(`0x${maximumAllowedHashValue}`);
|
|
97
|
+
|
|
98
|
+
let iterations = 1;
|
|
99
|
+
let responseNonce;
|
|
100
|
+
let qualifiedSolutionNonceFound = false;
|
|
101
|
+
do {
|
|
102
|
+
responseNonce = await this.generateNonce();
|
|
103
|
+
const computedHash = await DwnRegistrar.hashAsHexString(challengeNonce + responseNonce + requestData);
|
|
104
|
+
const computedHashAsBigInt = BigInt(`0x${computedHash}`);
|
|
105
|
+
|
|
106
|
+
qualifiedSolutionNonceFound = computedHashAsBigInt <= maximumAllowedHashValueAsBigInt;
|
|
107
|
+
|
|
108
|
+
iterations++;
|
|
109
|
+
} while (!qualifiedSolutionNonceFound);
|
|
110
|
+
|
|
111
|
+
// Log final/successful iteration.
|
|
112
|
+
console.log(
|
|
113
|
+
`iterations: ${iterations}, time lapsed: ${Date.now() - startTime} ms`,
|
|
114
|
+
);
|
|
115
|
+
|
|
116
|
+
return responseNonce;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Generates 32 random bytes expressed as a HEX string.
|
|
121
|
+
*/
|
|
122
|
+
public static async generateNonce(): Promise<string> {
|
|
123
|
+
const randomBytes = CryptoUtils.randomBytes(32);
|
|
124
|
+
const hexString = Convert.uint8Array(randomBytes).toHex().toUpperCase();
|
|
125
|
+
return hexString;
|
|
126
|
+
}
|
|
127
|
+
}
|