wowok 2.1.40 → 2.2.0
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/cjs/bcs/bcs.js +1 -253
- package/dist/cjs/bcs/effects.js +1 -199
- package/dist/cjs/bcs/index.js +1 -51
- package/dist/cjs/bcs/pure.js +1 -36
- package/dist/cjs/bcs/type-tag-serializer.js +1 -104
- package/dist/cjs/bcs/types.js +1 -3
- package/dist/cjs/client/index.js +1 -4
- package/dist/cjs/client/network.js +1 -15
- package/dist/cjs/cryptography/index.js +1 -6
- package/dist/cjs/cryptography/intent.js +1 -14
- package/dist/cjs/cryptography/keypair.js +1 -74
- package/dist/cjs/cryptography/mnemonics.js +1 -20
- package/dist/cjs/cryptography/publickey.js +1 -80
- package/dist/cjs/cryptography/signature-scheme.js +1 -22
- package/dist/cjs/cryptography/signature.js +1 -41
- package/dist/cjs/experimental/cache.js +1 -58
- package/dist/cjs/experimental/client.js +1 -19
- package/dist/cjs/experimental/core.js +1 -80
- package/dist/cjs/experimental/errors.js +1 -24
- package/dist/cjs/experimental/index.js +1 -5
- package/dist/cjs/experimental/persistent-storage.js +1 -220
- package/dist/cjs/experimental/persistent-storage.test.js +1 -144
- package/dist/cjs/experimental/transports/utils.js +1 -96
- package/dist/cjs/experimental/types.js +1 -1
- package/dist/cjs/faucet/faucet.js +1 -99
- package/dist/cjs/faucet/index.js +1 -1
- package/dist/cjs/grpc/client.js +1 -42
- package/dist/cjs/grpc/core.js +1 -587
- package/dist/cjs/grpc/index.js +1 -2
- package/dist/cjs/grpc/proto/google/protobuf/any.js +1 -106
- package/dist/cjs/grpc/proto/google/protobuf/duration.js +1 -58
- package/dist/cjs/grpc/proto/google/protobuf/empty.js +1 -7
- package/dist/cjs/grpc/proto/google/protobuf/field_mask.js +1 -47
- package/dist/cjs/grpc/proto/google/protobuf/struct.js +1 -191
- package/dist/cjs/grpc/proto/google/protobuf/timestamp.js +1 -91
- package/dist/cjs/grpc/proto/google/rpc/error_details.js +1 -265
- package/dist/cjs/grpc/proto/google/rpc/status.js +1 -23
- package/dist/cjs/grpc/proto/sui/rpc/v2/argument.js +1 -46
- package/dist/cjs/grpc/proto/sui/rpc/v2/balance_change.js +1 -29
- package/dist/cjs/grpc/proto/sui/rpc/v2/bcs.js +1 -22
- package/dist/cjs/grpc/proto/sui/rpc/v2/checkpoint.js +1 -54
- package/dist/cjs/grpc/proto/sui/rpc/v2/checkpoint_contents.js +1 -60
- package/dist/cjs/grpc/proto/sui/rpc/v2/checkpoint_summary.js +1 -144
- package/dist/cjs/grpc/proto/sui/rpc/v2/effects.js +1 -271
- package/dist/cjs/grpc/proto/sui/rpc/v2/epoch.js +1 -64
- package/dist/cjs/grpc/proto/sui/rpc/v2/error_reason.js +1 -6
- package/dist/cjs/grpc/proto/sui/rpc/v2/event.js +1 -62
- package/dist/cjs/grpc/proto/sui/rpc/v2/executed_transaction.js +1 -64
- package/dist/cjs/grpc/proto/sui/rpc/v2/execution_status.js +1 -481
- package/dist/cjs/grpc/proto/sui/rpc/v2/gas_cost_summary.js +1 -40
- package/dist/cjs/grpc/proto/sui/rpc/v2/input.js +1 -61
- package/dist/cjs/grpc/proto/sui/rpc/v2/jwk.js +1 -57
- package/dist/cjs/grpc/proto/sui/rpc/v2/ledger_service.client.js +1 -39
- package/dist/cjs/grpc/proto/sui/rpc/v2/ledger_service.js +1 -329
- package/dist/cjs/grpc/proto/sui/rpc/v2/move_package.js +1 -447
- package/dist/cjs/grpc/proto/sui/rpc/v2/move_package_service.client.js +1 -27
- package/dist/cjs/grpc/proto/sui/rpc/v2/move_package_service.js +1 -206
- package/dist/cjs/grpc/proto/sui/rpc/v2/name_service.client.js +1 -19
- package/dist/cjs/grpc/proto/sui/rpc/v2/name_service.js +1 -109
- package/dist/cjs/grpc/proto/sui/rpc/v2/object.js +1 -90
- package/dist/cjs/grpc/proto/sui/rpc/v2/object_reference.js +1 -30
- package/dist/cjs/grpc/proto/sui/rpc/v2/owner.js +1 -39
- package/dist/cjs/grpc/proto/sui/rpc/v2/protocol_config.js +1 -30
- package/dist/cjs/grpc/proto/sui/rpc/v2/signature.js +1 -501
- package/dist/cjs/grpc/proto/sui/rpc/v2/signature_scheme.js +1 -10
- package/dist/cjs/grpc/proto/sui/rpc/v2/signature_verification_service.client.js +1 -15
- package/dist/cjs/grpc/proto/sui/rpc/v2/signature_verification_service.js +1 -62
- package/dist/cjs/grpc/proto/sui/rpc/v2/state_service.client.js +1 -31
- package/dist/cjs/grpc/proto/sui/rpc/v2/state_service.js +1 -504
- package/dist/cjs/grpc/proto/sui/rpc/v2/subscription_service.client.js +1 -15
- package/dist/cjs/grpc/proto/sui/rpc/v2/subscription_service.js +1 -37
- package/dist/cjs/grpc/proto/sui/rpc/v2/system_state.js +1 -709
- package/dist/cjs/grpc/proto/sui/rpc/v2/transaction.js +1 -950
- package/dist/cjs/grpc/proto/sui/rpc/v2/transaction_execution_service.client.js +1 -19
- package/dist/cjs/grpc/proto/sui/rpc/v2/transaction_execution_service.js +1 -144
- package/dist/cjs/index.js +1 -22
- package/dist/cjs/jsonRpc/client.js +1 -516
- package/dist/cjs/jsonRpc/core.js +1 -587
- package/dist/cjs/jsonRpc/errors.js +1 -38
- package/dist/cjs/jsonRpc/http-transport.js +1 -70
- package/dist/cjs/jsonRpc/index.js +1 -3
- package/dist/cjs/jsonRpc/json-rpc-resolver.js +1 -296
- package/dist/cjs/jsonRpc/rpc-websocket-client.js +1 -155
- package/dist/cjs/jsonRpc/types/chain.js +1 -1
- package/dist/cjs/jsonRpc/types/changes.js +1 -1
- package/dist/cjs/jsonRpc/types/coins.js +1 -1
- package/dist/cjs/jsonRpc/types/common.js +1 -1
- package/dist/cjs/jsonRpc/types/generated.js +1 -1
- package/dist/cjs/jsonRpc/types/index.js +1 -1
- package/dist/cjs/jsonRpc/types/params.js +1 -1
- package/dist/cjs/keypairs/ed25519/ed25519-hd-key.js +1 -58
- package/dist/cjs/keypairs/ed25519/index.js +1 -2
- package/dist/cjs/keypairs/ed25519/keypair.js +1 -90
- package/dist/cjs/keypairs/ed25519/publickey.js +1 -50
- package/dist/cjs/keypairs/index.js +1 -4
- package/dist/cjs/keypairs/passkey/index.js +1 -2
- package/dist/cjs/keypairs/passkey/keypair.js +1 -155
- package/dist/cjs/keypairs/passkey/publickey.js +1 -117
- package/dist/cjs/keypairs/passkey/types.js +1 -1
- package/dist/cjs/keypairs/secp256k1/index.js +1 -2
- package/dist/cjs/keypairs/secp256k1/keypair.js +1 -82
- package/dist/cjs/keypairs/secp256k1/publickey.js +1 -51
- package/dist/cjs/keypairs/secp256r1/index.js +1 -2
- package/dist/cjs/keypairs/secp256r1/keypair.js +1 -78
- package/dist/cjs/keypairs/secp256r1/publickey.js +1 -52
- package/dist/cjs/multisig/index.js +1 -2
- package/dist/cjs/multisig/publickey.js +1 -201
- package/dist/cjs/multisig/signer.js +1 -58
- package/dist/cjs/transactions/Arguments.js +1 -9
- package/dist/cjs/transactions/Commands.js +1 -102
- package/dist/cjs/transactions/Inputs.js +1 -52
- package/dist/cjs/transactions/ObjectCache.js +1 -205
- package/dist/cjs/transactions/Transaction.js +1 -574
- package/dist/cjs/transactions/TransactionData.js +1 -409
- package/dist/cjs/transactions/__tests__/Transaction.test.js +1 -160
- package/dist/cjs/transactions/__tests__/bcs.test.js +1 -182
- package/dist/cjs/transactions/data/internal.js +1 -169
- package/dist/cjs/transactions/data/v1.js +1 -469
- package/dist/cjs/transactions/data/v2.js +1 -97
- package/dist/cjs/transactions/executor/caching.js +1 -65
- package/dist/cjs/transactions/executor/parallel.js +1 -347
- package/dist/cjs/transactions/executor/queue.js +1 -59
- package/dist/cjs/transactions/executor/serial.js +1 -99
- package/dist/cjs/transactions/hash.js +1 -8
- package/dist/cjs/transactions/index.js +1 -12
- package/dist/cjs/transactions/intents/CoinWithBalance.js +1 -145
- package/dist/cjs/transactions/object.js +1 -87
- package/dist/cjs/transactions/plugins/NamedPackagesPlugin.js +1 -11
- package/dist/cjs/transactions/pure.js +1 -36
- package/dist/cjs/transactions/resolve.js +1 -69
- package/dist/cjs/transactions/serializer.js +1 -167
- package/dist/cjs/transactions/utils.js +1 -121
- package/dist/cjs/utils/constants.js +1 -18
- package/dist/cjs/utils/derived-objects.js +1 -8
- package/dist/cjs/utils/dynamic-fields.js +1 -17
- package/dist/cjs/utils/format.js +1 -11
- package/dist/cjs/utils/index.js +1 -8
- package/dist/cjs/utils/move-registry.js +1 -24
- package/dist/cjs/utils/sui-types.js +1 -66
- package/dist/cjs/utils/suins.js +1 -33
- package/dist/cjs/verify/index.js +1 -1
- package/dist/cjs/verify/verify.js +1 -87
- package/dist/cjs/version.js +1 -2
- package/dist/cjs/w/call/allocation.js +1 -345
- package/dist/cjs/w/call/arb.js +1 -103
- package/dist/cjs/w/call/arbitration.js +1 -1192
- package/dist/cjs/w/call/base.js +1 -293
- package/dist/cjs/w/call/contact.js +1 -345
- package/dist/cjs/w/call/demand.js +1 -681
- package/dist/cjs/w/call/entity.js +1 -173
- package/dist/cjs/w/call/guard-ins.js +1 -4449
- package/dist/cjs/w/call/guard.d.ts +113 -0
- package/dist/cjs/w/call/guard.js +1 -1048
- package/dist/cjs/w/call/index.js +1 -22
- package/dist/cjs/w/call/machine.js +1 -1127
- package/dist/cjs/w/call/order.js +1 -337
- package/dist/cjs/w/call/passport.js +1 -220
- package/dist/cjs/w/call/payment.js +1 -178
- package/dist/cjs/w/call/permission.js +1 -1162
- package/dist/cjs/w/call/personal.js +1 -139
- package/dist/cjs/w/call/progress.js +1 -678
- package/dist/cjs/w/call/proof.js +1 -66
- package/dist/cjs/w/call/repository.js +1 -1024
- package/dist/cjs/w/call/resource.js +1 -108
- package/dist/cjs/w/call/reward.js +1 -675
- package/dist/cjs/w/call/service.js +1 -1960
- package/dist/cjs/w/call/treasury.js +1 -873
- package/dist/cjs/w/call/util.d.ts +1 -0
- package/dist/cjs/w/call/util.js +1 -566
- package/dist/cjs/w/common.js +1 -571
- package/dist/cjs/w/exception.js +1 -618
- package/dist/cjs/w/index.js +1 -8
- package/dist/cjs/w/local/account.js +1 -656
- package/dist/cjs/w/local/cache.js +1 -161
- package/dist/cjs/w/local/config.js +1 -43
- package/dist/cjs/w/local/index.js +1 -228
- package/dist/cjs/w/local/local.js +1 -574
- package/dist/cjs/w/local/storage.js +1 -185
- package/dist/cjs/w/local/token.js +1 -131
- package/dist/cjs/w/local/util.js +1 -26
- package/dist/cjs/w/local/wip.js +1 -864
- package/dist/cjs/w/messenger/crypto.js +1 -380
- package/dist/cjs/w/messenger/index.js +1 -4
- package/dist/cjs/w/messenger/messenger-api.js +1 -1154
- package/dist/cjs/w/messenger/messenger-manager.js +1 -1003
- package/dist/cjs/w/messenger/messenger.js +1 -1093
- package/dist/cjs/w/messenger/server.js +1 -343
- package/dist/cjs/w/messenger/session.js +1 -628
- package/dist/cjs/w/messenger/storage.js +1 -1023
- package/dist/cjs/w/messenger/templates/wts-html-template.js +1 -371
- package/dist/cjs/w/messenger/types.js +1 -76
- package/dist/cjs/w/messenger/utils.js +1 -12
- package/dist/cjs/w/query/bult-in.js +1 -95
- package/dist/cjs/w/query/event.js +1 -137
- package/dist/cjs/w/query/index.js +1 -5
- package/dist/cjs/w/query/object.js +1 -1550
- package/dist/cjs/w/query/received.js +1 -62
- package/dist/cjs/w/query/util.js +1 -49
- package/dist/cjs/w/util.js +1 -587
- package/dist/esm/bcs/bcs.js +1 -253
- package/dist/esm/bcs/effects.js +1 -199
- package/dist/esm/bcs/index.js +1 -51
- package/dist/esm/bcs/pure.js +1 -36
- package/dist/esm/bcs/type-tag-serializer.js +1 -104
- package/dist/esm/bcs/types.js +1 -3
- package/dist/esm/client/index.js +1 -4
- package/dist/esm/client/network.js +1 -15
- package/dist/esm/cryptography/index.js +1 -6
- package/dist/esm/cryptography/intent.js +1 -14
- package/dist/esm/cryptography/keypair.js +1 -74
- package/dist/esm/cryptography/mnemonics.js +1 -20
- package/dist/esm/cryptography/publickey.js +1 -80
- package/dist/esm/cryptography/signature-scheme.js +1 -22
- package/dist/esm/cryptography/signature.js +1 -41
- package/dist/esm/experimental/cache.js +1 -58
- package/dist/esm/experimental/client.js +1 -19
- package/dist/esm/experimental/core.js +1 -80
- package/dist/esm/experimental/errors.js +1 -24
- package/dist/esm/experimental/index.js +1 -5
- package/dist/esm/experimental/persistent-storage.js +1 -220
- package/dist/esm/experimental/persistent-storage.test.js +1 -144
- package/dist/esm/experimental/transports/utils.js +1 -96
- package/dist/esm/experimental/types.js +1 -1
- package/dist/esm/faucet/faucet.js +1 -99
- package/dist/esm/faucet/index.js +1 -1
- package/dist/esm/grpc/client.js +1 -42
- package/dist/esm/grpc/core.js +1 -587
- package/dist/esm/grpc/index.js +1 -2
- package/dist/esm/grpc/proto/google/protobuf/any.js +1 -106
- package/dist/esm/grpc/proto/google/protobuf/duration.js +1 -58
- package/dist/esm/grpc/proto/google/protobuf/empty.js +1 -7
- package/dist/esm/grpc/proto/google/protobuf/field_mask.js +1 -47
- package/dist/esm/grpc/proto/google/protobuf/struct.js +1 -191
- package/dist/esm/grpc/proto/google/protobuf/timestamp.js +1 -91
- package/dist/esm/grpc/proto/google/rpc/error_details.js +1 -265
- package/dist/esm/grpc/proto/google/rpc/status.js +1 -23
- package/dist/esm/grpc/proto/sui/rpc/v2/argument.js +1 -46
- package/dist/esm/grpc/proto/sui/rpc/v2/balance_change.js +1 -29
- package/dist/esm/grpc/proto/sui/rpc/v2/bcs.js +1 -22
- package/dist/esm/grpc/proto/sui/rpc/v2/checkpoint.js +1 -54
- package/dist/esm/grpc/proto/sui/rpc/v2/checkpoint_contents.js +1 -60
- package/dist/esm/grpc/proto/sui/rpc/v2/checkpoint_summary.js +1 -144
- package/dist/esm/grpc/proto/sui/rpc/v2/effects.js +1 -271
- package/dist/esm/grpc/proto/sui/rpc/v2/epoch.js +1 -64
- package/dist/esm/grpc/proto/sui/rpc/v2/error_reason.js +1 -6
- package/dist/esm/grpc/proto/sui/rpc/v2/event.js +1 -62
- package/dist/esm/grpc/proto/sui/rpc/v2/executed_transaction.js +1 -64
- package/dist/esm/grpc/proto/sui/rpc/v2/execution_status.js +1 -481
- package/dist/esm/grpc/proto/sui/rpc/v2/gas_cost_summary.js +1 -40
- package/dist/esm/grpc/proto/sui/rpc/v2/input.js +1 -61
- package/dist/esm/grpc/proto/sui/rpc/v2/jwk.js +1 -57
- package/dist/esm/grpc/proto/sui/rpc/v2/ledger_service.client.js +1 -39
- package/dist/esm/grpc/proto/sui/rpc/v2/ledger_service.js +1 -329
- package/dist/esm/grpc/proto/sui/rpc/v2/move_package.js +1 -447
- package/dist/esm/grpc/proto/sui/rpc/v2/move_package_service.client.js +1 -27
- package/dist/esm/grpc/proto/sui/rpc/v2/move_package_service.js +1 -206
- package/dist/esm/grpc/proto/sui/rpc/v2/name_service.client.js +1 -19
- package/dist/esm/grpc/proto/sui/rpc/v2/name_service.js +1 -109
- package/dist/esm/grpc/proto/sui/rpc/v2/object.js +1 -90
- package/dist/esm/grpc/proto/sui/rpc/v2/object_reference.js +1 -30
- package/dist/esm/grpc/proto/sui/rpc/v2/owner.js +1 -39
- package/dist/esm/grpc/proto/sui/rpc/v2/protocol_config.js +1 -30
- package/dist/esm/grpc/proto/sui/rpc/v2/signature.js +1 -501
- package/dist/esm/grpc/proto/sui/rpc/v2/signature_scheme.js +1 -10
- package/dist/esm/grpc/proto/sui/rpc/v2/signature_verification_service.client.js +1 -15
- package/dist/esm/grpc/proto/sui/rpc/v2/signature_verification_service.js +1 -62
- package/dist/esm/grpc/proto/sui/rpc/v2/state_service.client.js +1 -31
- package/dist/esm/grpc/proto/sui/rpc/v2/state_service.js +1 -504
- package/dist/esm/grpc/proto/sui/rpc/v2/subscription_service.client.js +1 -15
- package/dist/esm/grpc/proto/sui/rpc/v2/subscription_service.js +1 -37
- package/dist/esm/grpc/proto/sui/rpc/v2/system_state.js +1 -709
- package/dist/esm/grpc/proto/sui/rpc/v2/transaction.js +1 -950
- package/dist/esm/grpc/proto/sui/rpc/v2/transaction_execution_service.client.js +1 -19
- package/dist/esm/grpc/proto/sui/rpc/v2/transaction_execution_service.js +1 -144
- package/dist/esm/index.js +1 -22
- package/dist/esm/jsonRpc/client.js +1 -516
- package/dist/esm/jsonRpc/core.js +1 -587
- package/dist/esm/jsonRpc/errors.js +1 -38
- package/dist/esm/jsonRpc/http-transport.js +1 -70
- package/dist/esm/jsonRpc/index.js +1 -3
- package/dist/esm/jsonRpc/json-rpc-resolver.js +1 -296
- package/dist/esm/jsonRpc/rpc-websocket-client.js +1 -155
- package/dist/esm/jsonRpc/types/chain.js +1 -1
- package/dist/esm/jsonRpc/types/changes.js +1 -1
- package/dist/esm/jsonRpc/types/coins.js +1 -1
- package/dist/esm/jsonRpc/types/common.js +1 -1
- package/dist/esm/jsonRpc/types/generated.js +1 -1
- package/dist/esm/jsonRpc/types/index.js +1 -1
- package/dist/esm/jsonRpc/types/params.js +1 -1
- package/dist/esm/keypairs/ed25519/ed25519-hd-key.js +1 -58
- package/dist/esm/keypairs/ed25519/index.js +1 -2
- package/dist/esm/keypairs/ed25519/keypair.js +1 -90
- package/dist/esm/keypairs/ed25519/publickey.js +1 -50
- package/dist/esm/keypairs/index.js +1 -4
- package/dist/esm/keypairs/passkey/index.js +1 -2
- package/dist/esm/keypairs/passkey/keypair.js +1 -155
- package/dist/esm/keypairs/passkey/publickey.js +1 -117
- package/dist/esm/keypairs/passkey/types.js +1 -1
- package/dist/esm/keypairs/secp256k1/index.js +1 -2
- package/dist/esm/keypairs/secp256k1/keypair.js +1 -82
- package/dist/esm/keypairs/secp256k1/publickey.js +1 -51
- package/dist/esm/keypairs/secp256r1/index.js +1 -2
- package/dist/esm/keypairs/secp256r1/keypair.js +1 -78
- package/dist/esm/keypairs/secp256r1/publickey.js +1 -52
- package/dist/esm/multisig/index.js +1 -2
- package/dist/esm/multisig/publickey.js +1 -201
- package/dist/esm/multisig/signer.js +1 -58
- package/dist/esm/transactions/Arguments.js +1 -9
- package/dist/esm/transactions/Commands.js +1 -102
- package/dist/esm/transactions/Inputs.js +1 -52
- package/dist/esm/transactions/ObjectCache.js +1 -205
- package/dist/esm/transactions/Transaction.js +1 -574
- package/dist/esm/transactions/TransactionData.js +1 -409
- package/dist/esm/transactions/__tests__/Transaction.test.js +1 -160
- package/dist/esm/transactions/__tests__/bcs.test.js +1 -182
- package/dist/esm/transactions/data/internal.js +1 -169
- package/dist/esm/transactions/data/v1.js +1 -469
- package/dist/esm/transactions/data/v2.js +1 -97
- package/dist/esm/transactions/executor/caching.js +1 -65
- package/dist/esm/transactions/executor/parallel.js +1 -347
- package/dist/esm/transactions/executor/queue.js +1 -59
- package/dist/esm/transactions/executor/serial.js +1 -99
- package/dist/esm/transactions/hash.js +1 -8
- package/dist/esm/transactions/index.js +1 -12
- package/dist/esm/transactions/intents/CoinWithBalance.js +1 -145
- package/dist/esm/transactions/object.js +1 -87
- package/dist/esm/transactions/plugins/NamedPackagesPlugin.js +1 -11
- package/dist/esm/transactions/pure.js +1 -36
- package/dist/esm/transactions/resolve.js +1 -69
- package/dist/esm/transactions/serializer.js +1 -167
- package/dist/esm/transactions/utils.js +1 -121
- package/dist/esm/utils/constants.js +1 -18
- package/dist/esm/utils/derived-objects.js +1 -8
- package/dist/esm/utils/dynamic-fields.js +1 -17
- package/dist/esm/utils/format.js +1 -11
- package/dist/esm/utils/index.js +1 -8
- package/dist/esm/utils/move-registry.js +1 -24
- package/dist/esm/utils/sui-types.js +1 -66
- package/dist/esm/utils/suins.js +1 -33
- package/dist/esm/verify/index.js +1 -1
- package/dist/esm/verify/verify.js +1 -87
- package/dist/esm/version.js +1 -2
- package/dist/esm/w/call/allocation.js +1 -345
- package/dist/esm/w/call/arb.js +1 -103
- package/dist/esm/w/call/arbitration.js +1 -1192
- package/dist/esm/w/call/base.js +1 -293
- package/dist/esm/w/call/contact.js +1 -345
- package/dist/esm/w/call/demand.js +1 -681
- package/dist/esm/w/call/entity.js +1 -173
- package/dist/esm/w/call/guard-ins.js +1 -4449
- package/dist/esm/w/call/guard.d.ts +113 -0
- package/dist/esm/w/call/guard.js +1 -1048
- package/dist/esm/w/call/index.js +1 -22
- package/dist/esm/w/call/machine.js +1 -1127
- package/dist/esm/w/call/order.js +1 -337
- package/dist/esm/w/call/passport.js +1 -220
- package/dist/esm/w/call/payment.js +1 -178
- package/dist/esm/w/call/permission.js +1 -1162
- package/dist/esm/w/call/personal.js +1 -139
- package/dist/esm/w/call/progress.js +1 -678
- package/dist/esm/w/call/proof.js +1 -66
- package/dist/esm/w/call/repository.js +1 -1024
- package/dist/esm/w/call/resource.js +1 -108
- package/dist/esm/w/call/reward.js +1 -675
- package/dist/esm/w/call/service.js +1 -1960
- package/dist/esm/w/call/treasury.js +1 -873
- package/dist/esm/w/call/util.d.ts +1 -0
- package/dist/esm/w/call/util.js +1 -566
- package/dist/esm/w/common.js +1 -571
- package/dist/esm/w/exception.js +1 -618
- package/dist/esm/w/index.js +1 -8
- package/dist/esm/w/local/account.js +1 -656
- package/dist/esm/w/local/cache.js +1 -161
- package/dist/esm/w/local/config.js +1 -43
- package/dist/esm/w/local/index.js +1 -228
- package/dist/esm/w/local/local.js +1 -574
- package/dist/esm/w/local/storage.js +1 -185
- package/dist/esm/w/local/token.js +1 -131
- package/dist/esm/w/local/util.js +1 -26
- package/dist/esm/w/local/wip.js +1 -864
- package/dist/esm/w/messenger/crypto.js +1 -380
- package/dist/esm/w/messenger/index.js +1 -4
- package/dist/esm/w/messenger/messenger-api.js +1 -1154
- package/dist/esm/w/messenger/messenger-manager.js +1 -1003
- package/dist/esm/w/messenger/messenger.js +1 -1093
- package/dist/esm/w/messenger/server.js +1 -343
- package/dist/esm/w/messenger/session.js +1 -628
- package/dist/esm/w/messenger/storage.js +1 -1023
- package/dist/esm/w/messenger/templates/wts-html-template.js +1 -371
- package/dist/esm/w/messenger/types.js +1 -76
- package/dist/esm/w/messenger/utils.js +1 -12
- package/dist/esm/w/query/bult-in.js +1 -95
- package/dist/esm/w/query/event.js +1 -137
- package/dist/esm/w/query/index.js +1 -5
- package/dist/esm/w/query/object.js +1 -1550
- package/dist/esm/w/query/received.js +1 -62
- package/dist/esm/w/query/util.js +1 -49
- package/dist/esm/w/util.js +1 -587
- package/package.json +5 -2
package/dist/esm/w/local/wip.js
CHANGED
|
@@ -1,864 +1 @@
|
|
|
1
|
-
import { sha256 } from "@noble/hashes/sha256";
|
|
2
|
-
import { bytesToHex } from "@noble/hashes/utils";
|
|
3
|
-
import * as fs from "fs";
|
|
4
|
-
import * as path from "path";
|
|
5
|
-
import * as https from "https";
|
|
6
|
-
import * as http from "http";
|
|
7
|
-
const WIP_SCHEMA_URL = "https://schema.wowok.net/wip/v1";
|
|
8
|
-
const WIP_VERSION = "1.0.0";
|
|
9
|
-
export const DEFAULT_LIMITS = {
|
|
10
|
-
maxImageSize: 2 * 1024 * 1024,
|
|
11
|
-
maxTotalSize: 10 * 1024 * 1024,
|
|
12
|
-
maxImageCount: 10,
|
|
13
|
-
maxTextLength: 10000,
|
|
14
|
-
};
|
|
15
|
-
export class WipError extends Error {
|
|
16
|
-
constructor(message) {
|
|
17
|
-
super(message);
|
|
18
|
-
this.name = "WipError";
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
export class WipValidationError extends WipError {
|
|
22
|
-
constructor(message) {
|
|
23
|
-
super(message);
|
|
24
|
-
this.name = "WipValidationError";
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
export class WipSizeError extends WipError {
|
|
28
|
-
constructor(message) {
|
|
29
|
-
super(message);
|
|
30
|
-
this.name = "WipSizeError";
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
function detectMimeType(buffer) {
|
|
34
|
-
if (buffer.length >= 4 &&
|
|
35
|
-
buffer[0] === 0x89 &&
|
|
36
|
-
buffer[1] === 0x50 &&
|
|
37
|
-
buffer[2] === 0x4e &&
|
|
38
|
-
buffer[3] === 0x47) {
|
|
39
|
-
return "image/png";
|
|
40
|
-
}
|
|
41
|
-
if (buffer.length >= 3 &&
|
|
42
|
-
buffer[0] === 0xff &&
|
|
43
|
-
buffer[1] === 0xd8 &&
|
|
44
|
-
buffer[2] === 0xff) {
|
|
45
|
-
return "image/jpeg";
|
|
46
|
-
}
|
|
47
|
-
if (buffer.length >= 6 &&
|
|
48
|
-
buffer[0] === 0x47 &&
|
|
49
|
-
buffer[1] === 0x49 &&
|
|
50
|
-
buffer[2] === 0x46) {
|
|
51
|
-
return "image/gif";
|
|
52
|
-
}
|
|
53
|
-
if (buffer.length >= 12 &&
|
|
54
|
-
buffer[0] === 0x52 &&
|
|
55
|
-
buffer[1] === 0x49 &&
|
|
56
|
-
buffer[2] === 0x46 &&
|
|
57
|
-
buffer[3] === 0x46 &&
|
|
58
|
-
buffer[8] === 0x57 &&
|
|
59
|
-
buffer[9] === 0x45 &&
|
|
60
|
-
buffer[10] === 0x42 &&
|
|
61
|
-
buffer[11] === 0x50) {
|
|
62
|
-
return "image/webp";
|
|
63
|
-
}
|
|
64
|
-
return null;
|
|
65
|
-
}
|
|
66
|
-
function uint8ArrayToBase64(array) {
|
|
67
|
-
let binary = "";
|
|
68
|
-
const len = array.length;
|
|
69
|
-
for (let i = 0; i < len; i++) {
|
|
70
|
-
binary += String.fromCharCode(array[i]);
|
|
71
|
-
}
|
|
72
|
-
return btoa(binary);
|
|
73
|
-
}
|
|
74
|
-
function base64ToUint8Array(base64) {
|
|
75
|
-
const binary = atob(base64);
|
|
76
|
-
const len = binary.length;
|
|
77
|
-
const array = new Uint8Array(len);
|
|
78
|
-
for (let i = 0; i < len; i++) {
|
|
79
|
-
array[i] = binary.charCodeAt(i);
|
|
80
|
-
}
|
|
81
|
-
return array;
|
|
82
|
-
}
|
|
83
|
-
function canonicalizeJson(obj) {
|
|
84
|
-
if (obj === null || typeof obj !== "object") {
|
|
85
|
-
return JSON.stringify(obj);
|
|
86
|
-
}
|
|
87
|
-
if (Array.isArray(obj)) {
|
|
88
|
-
return "[" + obj.map(canonicalizeJson).join(",") + "]";
|
|
89
|
-
}
|
|
90
|
-
const sortedObj = obj;
|
|
91
|
-
const keys = Object.keys(sortedObj).sort();
|
|
92
|
-
const pairs = keys.map((key) => `"${key}":${canonicalizeJson(sortedObj[key])}`);
|
|
93
|
-
return "{" + pairs.join(",") + "}";
|
|
94
|
-
}
|
|
95
|
-
function computeHash(data) {
|
|
96
|
-
const hash = sha256(new TextEncoder().encode(data));
|
|
97
|
-
return bytesToHex(hash);
|
|
98
|
-
}
|
|
99
|
-
function generateId(prefix) {
|
|
100
|
-
const timestamp = Date.now().toString(36);
|
|
101
|
-
const random = Math.random().toString(36).substring(2, 8);
|
|
102
|
-
return `${prefix}-${timestamp}-${random}`;
|
|
103
|
-
}
|
|
104
|
-
function getExtensionFromMimeType(mimeType) {
|
|
105
|
-
const map = {
|
|
106
|
-
"image/png": "png",
|
|
107
|
-
"image/jpeg": "jpg",
|
|
108
|
-
"image/gif": "gif",
|
|
109
|
-
"image/webp": "webp",
|
|
110
|
-
};
|
|
111
|
-
return map[mimeType] || "bin";
|
|
112
|
-
}
|
|
113
|
-
class ResourceLoader {
|
|
114
|
-
maxSize;
|
|
115
|
-
constructor(maxSize) {
|
|
116
|
-
this.maxSize = maxSize;
|
|
117
|
-
}
|
|
118
|
-
async load(source) {
|
|
119
|
-
if (!source || source.trim() === "") {
|
|
120
|
-
throw new WipError("WIP file path cannot be empty");
|
|
121
|
-
}
|
|
122
|
-
if (source.startsWith("data:")) {
|
|
123
|
-
return this.loadFromDataUrl(source);
|
|
124
|
-
}
|
|
125
|
-
if (source.startsWith("http://") || source.startsWith("https://")) {
|
|
126
|
-
return this.loadFromNetwork(source);
|
|
127
|
-
}
|
|
128
|
-
return this.loadFromFile(source);
|
|
129
|
-
}
|
|
130
|
-
loadFromDataUrl(dataUrl) {
|
|
131
|
-
const match = dataUrl.match(/^data:image\/(\w+);base64,(.+)$/);
|
|
132
|
-
if (!match) {
|
|
133
|
-
throw new WipValidationError(`Invalid data URL format: ${dataUrl.substring(0, 50)}...`);
|
|
134
|
-
}
|
|
135
|
-
const base64Data = match[2];
|
|
136
|
-
try {
|
|
137
|
-
return base64ToUint8Array(base64Data);
|
|
138
|
-
}
|
|
139
|
-
catch (error) {
|
|
140
|
-
throw new WipError(`Failed to decode data URL: ${error}`);
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
async loadFromNetwork(url) {
|
|
144
|
-
return new Promise((resolve, reject) => {
|
|
145
|
-
const timeoutId = setTimeout(() => {
|
|
146
|
-
reject(new WipError(`Network timeout while fetching: ${url}`));
|
|
147
|
-
}, 30000);
|
|
148
|
-
const isHttps = url.startsWith("https:");
|
|
149
|
-
const client = isHttps ? https : http;
|
|
150
|
-
const options = {
|
|
151
|
-
headers: {
|
|
152
|
-
Accept: "application/json,*/*",
|
|
153
|
-
},
|
|
154
|
-
};
|
|
155
|
-
if (isHttps) {
|
|
156
|
-
options.rejectUnauthorized = false;
|
|
157
|
-
}
|
|
158
|
-
const request = client.get(url, options, (response) => {
|
|
159
|
-
clearTimeout(timeoutId);
|
|
160
|
-
if (response.statusCode !== 200) {
|
|
161
|
-
reject(new WipError(`Failed to fetch: ${response.statusCode} ${response.statusMessage}`));
|
|
162
|
-
return;
|
|
163
|
-
}
|
|
164
|
-
const contentLength = response.headers["content-length"];
|
|
165
|
-
if (contentLength && parseInt(contentLength) > this.maxSize) {
|
|
166
|
-
reject(new WipSizeError(`Resource from ${url} size (${contentLength} bytes) exceeds limit (${this.maxSize} bytes)`));
|
|
167
|
-
return;
|
|
168
|
-
}
|
|
169
|
-
const chunks = [];
|
|
170
|
-
response.on("data", (chunk) => {
|
|
171
|
-
chunks.push(chunk);
|
|
172
|
-
});
|
|
173
|
-
response.on("end", () => {
|
|
174
|
-
const buffer = Buffer.concat(chunks);
|
|
175
|
-
if (buffer.length > this.maxSize) {
|
|
176
|
-
reject(new WipSizeError(`Resource from ${url} size (${buffer.length} bytes) exceeds limit (${this.maxSize} bytes)`));
|
|
177
|
-
return;
|
|
178
|
-
}
|
|
179
|
-
resolve(new Uint8Array(buffer));
|
|
180
|
-
});
|
|
181
|
-
response.on("error", (error) => {
|
|
182
|
-
reject(new WipError(`Network error: ${error.message}`));
|
|
183
|
-
});
|
|
184
|
-
});
|
|
185
|
-
request.on("error", (error) => {
|
|
186
|
-
clearTimeout(timeoutId);
|
|
187
|
-
reject(new WipError(`Network error: ${error.message}`));
|
|
188
|
-
});
|
|
189
|
-
});
|
|
190
|
-
}
|
|
191
|
-
loadFromFile(filePath) {
|
|
192
|
-
const resolvedPath = path.resolve(filePath);
|
|
193
|
-
if (!fs.existsSync(resolvedPath)) {
|
|
194
|
-
throw new WipError(`File not found: ${resolvedPath}`);
|
|
195
|
-
}
|
|
196
|
-
const stats = fs.statSync(resolvedPath);
|
|
197
|
-
if (!stats.isFile()) {
|
|
198
|
-
throw new WipError(`Path is not a file: ${resolvedPath}`);
|
|
199
|
-
}
|
|
200
|
-
if (stats.size > this.maxSize) {
|
|
201
|
-
throw new WipSizeError(`File ${resolvedPath} size (${stats.size} bytes) exceeds limit (${this.maxSize} bytes)`);
|
|
202
|
-
}
|
|
203
|
-
const buffer = fs.readFileSync(resolvedPath);
|
|
204
|
-
return new Uint8Array(buffer);
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
export class WIP {
|
|
208
|
-
limits;
|
|
209
|
-
resourceLoader;
|
|
210
|
-
constructor(limits = {}) {
|
|
211
|
-
this.limits = { ...DEFAULT_LIMITS, ...limits };
|
|
212
|
-
this.resourceLoader = new ResourceLoader(this.limits.maxImageSize);
|
|
213
|
-
}
|
|
214
|
-
async create(options) {
|
|
215
|
-
if (options.text.length > this.limits.maxTextLength) {
|
|
216
|
-
throw new WipSizeError(`Text length (${options.text.length}) exceeds limit (${this.limits.maxTextLength})`);
|
|
217
|
-
}
|
|
218
|
-
const media = [];
|
|
219
|
-
if (options.images && options.images.length > 0) {
|
|
220
|
-
if (options.images.length > this.limits.maxImageCount) {
|
|
221
|
-
throw new WipSizeError(`Image count (${options.images.length}) exceeds limit (${this.limits.maxImageCount})`);
|
|
222
|
-
}
|
|
223
|
-
for (let i = 0; i < options.images.length; i++) {
|
|
224
|
-
const wipMedia = await this.processImage(options.images[i], i);
|
|
225
|
-
media.push(wipMedia);
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
const payload = {
|
|
229
|
-
content: {
|
|
230
|
-
text: options.text,
|
|
231
|
-
format: options.textFormat || "plain",
|
|
232
|
-
},
|
|
233
|
-
media,
|
|
234
|
-
};
|
|
235
|
-
const canonicalPayload = canonicalizeJson(payload);
|
|
236
|
-
const hash = computeHash(canonicalPayload);
|
|
237
|
-
const meta = {
|
|
238
|
-
type: "wip",
|
|
239
|
-
version: WIP_VERSION,
|
|
240
|
-
created: new Date().toISOString(),
|
|
241
|
-
hash,
|
|
242
|
-
algorithm: "sha256",
|
|
243
|
-
};
|
|
244
|
-
if (options.signKeyPair) {
|
|
245
|
-
const signatureValue = await this.sign(hash, options.signKeyPair.privateKey, options.signAlgorithm || "Ed25519");
|
|
246
|
-
meta.signature = {
|
|
247
|
-
value: signatureValue,
|
|
248
|
-
publicKey: options.signKeyPair.publicKey,
|
|
249
|
-
algorithm: options.signAlgorithm || "Ed25519",
|
|
250
|
-
};
|
|
251
|
-
}
|
|
252
|
-
const wipFile = {
|
|
253
|
-
wip: WIP_SCHEMA_URL,
|
|
254
|
-
payload,
|
|
255
|
-
meta,
|
|
256
|
-
};
|
|
257
|
-
const jsonString = JSON.stringify(wipFile);
|
|
258
|
-
if (jsonString.length > this.limits.maxTotalSize) {
|
|
259
|
-
throw new WipSizeError(`Total WIP file size (${jsonString.length} bytes) exceeds limit (${this.limits.maxTotalSize} bytes)`);
|
|
260
|
-
}
|
|
261
|
-
return wipFile;
|
|
262
|
-
}
|
|
263
|
-
async processImage(source, index) {
|
|
264
|
-
const data = await this.resourceLoader.load(source.source);
|
|
265
|
-
const mimeType = detectMimeType(data);
|
|
266
|
-
if (!mimeType) {
|
|
267
|
-
throw new WipValidationError(`Unsupported image format: ${source.source}`);
|
|
268
|
-
}
|
|
269
|
-
let filename = source.filename;
|
|
270
|
-
if (!filename) {
|
|
271
|
-
if (source.source.startsWith("http")) {
|
|
272
|
-
const url = new URL(source.source);
|
|
273
|
-
const pathname = url.pathname;
|
|
274
|
-
filename =
|
|
275
|
-
pathname.substring(pathname.lastIndexOf("/") + 1) ||
|
|
276
|
-
`image-${index}`;
|
|
277
|
-
}
|
|
278
|
-
else {
|
|
279
|
-
filename =
|
|
280
|
-
source.source.substring(source.source.lastIndexOf("/") + 1) || `image-${index}`;
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
return {
|
|
284
|
-
id: source.id || generateId("img"),
|
|
285
|
-
type: mimeType,
|
|
286
|
-
data: uint8ArrayToBase64(data),
|
|
287
|
-
filename,
|
|
288
|
-
};
|
|
289
|
-
}
|
|
290
|
-
async sign(data, privateKey, algorithm) {
|
|
291
|
-
if (algorithm !== "Ed25519") {
|
|
292
|
-
throw new WipError(`Unsupported signature algorithm: ${algorithm}`);
|
|
293
|
-
}
|
|
294
|
-
const { Ed25519Keypair } = await import("../../keypairs/ed25519/index.js");
|
|
295
|
-
const keypair = Ed25519Keypair.fromSecretKey(privateKey);
|
|
296
|
-
const signature = await keypair.sign(new TextEncoder().encode(data));
|
|
297
|
-
return uint8ArrayToBase64(signature);
|
|
298
|
-
}
|
|
299
|
-
async verify(wipFile) {
|
|
300
|
-
try {
|
|
301
|
-
if (!wipFile.wip || !wipFile.payload || !wipFile.meta) {
|
|
302
|
-
return { valid: false, error: "Invalid WIP file structure" };
|
|
303
|
-
}
|
|
304
|
-
if (wipFile.meta.type !== "wip") {
|
|
305
|
-
return {
|
|
306
|
-
valid: false,
|
|
307
|
-
error: `Invalid meta.type: ${wipFile.meta.type}`,
|
|
308
|
-
};
|
|
309
|
-
}
|
|
310
|
-
const canonicalPayload = canonicalizeJson(wipFile.payload);
|
|
311
|
-
const computedHash = computeHash(canonicalPayload);
|
|
312
|
-
if (computedHash !== wipFile.meta.hash) {
|
|
313
|
-
return {
|
|
314
|
-
valid: false,
|
|
315
|
-
error: "Hash mismatch - content has been tampered",
|
|
316
|
-
};
|
|
317
|
-
}
|
|
318
|
-
const signatures = [];
|
|
319
|
-
if (wipFile.meta.signature) {
|
|
320
|
-
const sigArray = Array.isArray(wipFile.meta.signature)
|
|
321
|
-
? wipFile.meta.signature
|
|
322
|
-
: [wipFile.meta.signature];
|
|
323
|
-
for (const sig of sigArray) {
|
|
324
|
-
const signValid = await this.verifySignature(wipFile.meta.hash, sig.value, sig.publicKey, sig.algorithm);
|
|
325
|
-
signatures.push({
|
|
326
|
-
address: sig.address,
|
|
327
|
-
valid: signValid,
|
|
328
|
-
});
|
|
329
|
-
if (!signValid) {
|
|
330
|
-
return {
|
|
331
|
-
valid: false,
|
|
332
|
-
error: "Invalid signature",
|
|
333
|
-
signatures,
|
|
334
|
-
};
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
}
|
|
338
|
-
return { valid: true, signatures };
|
|
339
|
-
}
|
|
340
|
-
catch (error) {
|
|
341
|
-
return { valid: false, error: `Verification error: ${error}` };
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
async verifySignature(data, signature, publicKey, algorithm) {
|
|
345
|
-
if (algorithm !== "Ed25519") {
|
|
346
|
-
throw new WipError(`Unsupported signature algorithm: ${algorithm}`);
|
|
347
|
-
}
|
|
348
|
-
try {
|
|
349
|
-
const { Ed25519PublicKey } = await import("../../keypairs/ed25519/publickey.js");
|
|
350
|
-
let pkToUse = publicKey;
|
|
351
|
-
if (publicKey.startsWith("0x")) {
|
|
352
|
-
const buffer = Buffer.from(publicKey.slice(2), "hex");
|
|
353
|
-
if (buffer.length === 33) {
|
|
354
|
-
pkToUse = buffer.slice(1).toString("base64");
|
|
355
|
-
}
|
|
356
|
-
else if (buffer.length === 32) {
|
|
357
|
-
pkToUse = buffer.toString("base64");
|
|
358
|
-
}
|
|
359
|
-
}
|
|
360
|
-
else {
|
|
361
|
-
try {
|
|
362
|
-
const buffer = Buffer.from(publicKey, "base64");
|
|
363
|
-
if (buffer.length === 33) {
|
|
364
|
-
pkToUse = buffer.slice(1).toString("base64");
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
catch {
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
const pubKey = new Ed25519PublicKey(pkToUse);
|
|
371
|
-
const signatureBytes = Uint8Array.from(Buffer.from(signature, "base64"));
|
|
372
|
-
return await pubKey.verify(new TextEncoder().encode(data), signatureBytes);
|
|
373
|
-
}
|
|
374
|
-
catch (error) {
|
|
375
|
-
console.error("Signature verification error:", error);
|
|
376
|
-
return false;
|
|
377
|
-
}
|
|
378
|
-
}
|
|
379
|
-
async toHtml(wipFile, options = {}) {
|
|
380
|
-
const { title = "WIP Document", theme = "light" } = options;
|
|
381
|
-
const { payload, meta } = wipFile;
|
|
382
|
-
const escapeHtml = (text) => {
|
|
383
|
-
return text
|
|
384
|
-
.replace(/&/g, "&")
|
|
385
|
-
.replace(/</g, "<")
|
|
386
|
-
.replace(/>/g, ">")
|
|
387
|
-
.replace(/"/g, """)
|
|
388
|
-
.replace(/'/g, "'");
|
|
389
|
-
};
|
|
390
|
-
const formatText = (text, format) => {
|
|
391
|
-
switch (format) {
|
|
392
|
-
case "html":
|
|
393
|
-
return text;
|
|
394
|
-
case "markdown":
|
|
395
|
-
return text
|
|
396
|
-
.replace(/\*\*(.+?)\*\*/g, "<strong>$1</strong>")
|
|
397
|
-
.replace(/\*(.+?)\*/g, "<em>$1</em>")
|
|
398
|
-
.replace(/\n/g, "<br>");
|
|
399
|
-
case "plain":
|
|
400
|
-
default:
|
|
401
|
-
return escapeHtml(text).replace(/\n/g, "<br>");
|
|
402
|
-
}
|
|
403
|
-
};
|
|
404
|
-
const bgColor = theme === "dark" ? "#1a1a1a" : "#ffffff";
|
|
405
|
-
const textColor = theme === "dark" ? "#e0e0e0" : "#333333";
|
|
406
|
-
const borderColor = theme === "dark" ? "#444444" : "#e0e0e0";
|
|
407
|
-
const verifiedColor = "#4caf50";
|
|
408
|
-
const warningColor = "#ff9800";
|
|
409
|
-
const verifyResult = await this.verify(wipFile);
|
|
410
|
-
const statusBadge = verifyResult.valid
|
|
411
|
-
? `<span style="background: ${verifiedColor}; color: white; padding: 4px 8px; border-radius: 4px; font-size: 12px;">✓ Verified</span>`
|
|
412
|
-
: `<span style="background: ${warningColor}; color: white; padding: 4px 8px; border-radius: 4px; font-size: 12px;">⚠ Tampered</span>`;
|
|
413
|
-
const imagesHtml = payload.media
|
|
414
|
-
.map((media) => `
|
|
415
|
-
<div style="margin: 16px 0; border: 1px solid ${borderColor}; border-radius: 8px; overflow: hidden;">
|
|
416
|
-
<img src="data:${media.type};base64,${media.data}"
|
|
417
|
-
style="max-width: 100%; height: auto; display: block;"
|
|
418
|
-
alt="${escapeHtml(media.filename || media.id)}" />
|
|
419
|
-
${media.filename ? `<div style="padding: 8px; font-size: 12px; color: #666; background: ${theme === "dark" ? "#2a2a2a" : "#f5f5f5"}; border-top: 1px solid ${borderColor};">${escapeHtml(media.filename)}</div>` : ""}
|
|
420
|
-
</div>
|
|
421
|
-
`)
|
|
422
|
-
.join("");
|
|
423
|
-
return `<!DOCTYPE html>
|
|
424
|
-
<html lang="en">
|
|
425
|
-
<head>
|
|
426
|
-
<meta charset="UTF-8">
|
|
427
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
428
|
-
<title>${escapeHtml(title)}</title>
|
|
429
|
-
</head>
|
|
430
|
-
<body style="margin: 0; padding: 20px; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; background: ${bgColor}; color: ${textColor}; line-height: 1.6;">
|
|
431
|
-
<div style="max-width: 800px; margin: 0 auto; background: ${theme === "dark" ? "#252525" : "#ffffff"}; border-radius: 12px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); overflow: hidden;">
|
|
432
|
-
<div style="padding: 20px 24px; border-bottom: 1px solid ${borderColor};">
|
|
433
|
-
<div style="display: flex; justify-content: space-between; align-items: center;">
|
|
434
|
-
<div>
|
|
435
|
-
<h1 style="margin: 0; font-size: 20px; font-weight: 600;">${escapeHtml(title)}</h1>
|
|
436
|
-
<div style="font-size: 12px; color: #666; margin-top: 4px;">
|
|
437
|
-
WIP v${meta.version} • ${new Date(meta.created).toLocaleString()}
|
|
438
|
-
</div>
|
|
439
|
-
</div>
|
|
440
|
-
${statusBadge}
|
|
441
|
-
</div>
|
|
442
|
-
<div style="font-size: 11px; color: #999; margin-top: 12px; padding: 8px; background: ${theme === "dark" ? "#2a2a2a" : "#f5f5f5"}; border-radius: 4px; font-style: italic;">
|
|
443
|
-
Important Note: This page is for document browsing and verification reference only. Please verify the document integrity through the API using the WIP file.
|
|
444
|
-
</div>
|
|
445
|
-
${verifyResult.signatures && verifyResult.signatures.length > 0
|
|
446
|
-
? `
|
|
447
|
-
<div style="margin-top: 12px; padding: 8px; background: ${theme === "dark" ? "#2a3f2a" : "#e8f5e9"}; border-radius: 4px;">
|
|
448
|
-
<div style="font-size: 11px; color: ${theme === "dark" ? "#81c784" : "#2e7d32"}; margin-bottom: 4px;">✓ Signature Verification (${verifyResult.signatures.length} signature${verifyResult.signatures.length > 1 ? "s" : ""})</div>
|
|
449
|
-
${verifyResult.signatures
|
|
450
|
-
.map((s, idx) => `
|
|
451
|
-
<div style="font-size: 10px; color: ${textColor}; margin-left: 8px;">
|
|
452
|
-
${idx + 1}. ${s.address ? escapeHtml(s.address.slice(0, 20)) + "..." : "Unknown"}: ${s.valid ? '<span style="color: #4caf50;">✓ Valid</span>' : '<span style="color: #f44336;">✗ Invalid</span>'}
|
|
453
|
-
</div>
|
|
454
|
-
`)
|
|
455
|
-
.join("")}
|
|
456
|
-
</div>
|
|
457
|
-
`
|
|
458
|
-
: ""}
|
|
459
|
-
</div>
|
|
460
|
-
<div style="padding: 24px;">
|
|
461
|
-
<div style="font-size: 16px; line-height: 1.8; margin-bottom: 24px;">
|
|
462
|
-
${formatText(payload.content.text, payload.content.format)}
|
|
463
|
-
</div>
|
|
464
|
-
${imagesHtml}
|
|
465
|
-
</div>
|
|
466
|
-
<div style="padding: 16px 24px; background: ${theme === "dark" ? "#2a2a2a" : "#f8f9fa"}; border-top: 1px solid ${borderColor}; font-size: 11px; color: #666;">
|
|
467
|
-
<div style="display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 8px;">
|
|
468
|
-
<div>
|
|
469
|
-
<strong>Hash:</strong> <code style="background: ${theme === "dark" ? "#333" : "#e9ecef"}; padding: 2px 6px; border-radius: 3px;">${escapeHtml(meta.hash)}</code>
|
|
470
|
-
</div>
|
|
471
|
-
<div>
|
|
472
|
-
${verifyResult.valid ? "Content integrity verified" : `Verification failed: ${escapeHtml(verifyResult.error || "Unknown error")}`}
|
|
473
|
-
</div>
|
|
474
|
-
</div>
|
|
475
|
-
</div>
|
|
476
|
-
</div>
|
|
477
|
-
</body>
|
|
478
|
-
</html>`;
|
|
479
|
-
}
|
|
480
|
-
stringify(wipFile, pretty = true) {
|
|
481
|
-
return pretty
|
|
482
|
-
? JSON.stringify(wipFile, null, 2)
|
|
483
|
-
: JSON.stringify(wipFile);
|
|
484
|
-
}
|
|
485
|
-
parse(jsonString) {
|
|
486
|
-
try {
|
|
487
|
-
const obj = JSON.parse(jsonString);
|
|
488
|
-
if (!obj.wip || !obj.payload || !obj.meta) {
|
|
489
|
-
throw new WipValidationError("Invalid WIP file structure");
|
|
490
|
-
}
|
|
491
|
-
return obj;
|
|
492
|
-
}
|
|
493
|
-
catch (error) {
|
|
494
|
-
if (error instanceof WipError) {
|
|
495
|
-
throw error;
|
|
496
|
-
}
|
|
497
|
-
throw new WipValidationError(`Failed to parse WIP file: ${error}`);
|
|
498
|
-
}
|
|
499
|
-
}
|
|
500
|
-
async load(source) {
|
|
501
|
-
const data = await this.resourceLoader.load(source);
|
|
502
|
-
const content = new TextDecoder().decode(data);
|
|
503
|
-
return this.parse(content);
|
|
504
|
-
}
|
|
505
|
-
getHash(wipFile) {
|
|
506
|
-
const hash = wipFile.meta.hash;
|
|
507
|
-
if (hash.includes(":")) {
|
|
508
|
-
return hash.split(":")[1];
|
|
509
|
-
}
|
|
510
|
-
return hash;
|
|
511
|
-
}
|
|
512
|
-
extractImages(wipFile, outputDir) {
|
|
513
|
-
if (!fs.existsSync(outputDir)) {
|
|
514
|
-
fs.mkdirSync(outputDir, { recursive: true });
|
|
515
|
-
}
|
|
516
|
-
const savedPaths = [];
|
|
517
|
-
for (const media of wipFile.payload.media) {
|
|
518
|
-
const ext = getExtensionFromMimeType(media.type);
|
|
519
|
-
const filename = media.filename || `${media.id}.${ext}`;
|
|
520
|
-
const outputPath = path.join(outputDir, filename);
|
|
521
|
-
const buffer = Buffer.from(base64ToUint8Array(media.data));
|
|
522
|
-
fs.writeFileSync(outputPath, buffer);
|
|
523
|
-
savedPaths.push(outputPath);
|
|
524
|
-
}
|
|
525
|
-
return savedPaths;
|
|
526
|
-
}
|
|
527
|
-
save(wipFile, filePath, pretty = true) {
|
|
528
|
-
const dir = path.dirname(filePath);
|
|
529
|
-
if (!fs.existsSync(dir)) {
|
|
530
|
-
fs.mkdirSync(dir, { recursive: true });
|
|
531
|
-
}
|
|
532
|
-
fs.writeFileSync(filePath, this.stringify(wipFile, pretty), "utf-8");
|
|
533
|
-
}
|
|
534
|
-
getLimits() {
|
|
535
|
-
return { ...this.limits };
|
|
536
|
-
}
|
|
537
|
-
setLimits(limits) {
|
|
538
|
-
this.limits = { ...this.limits, ...limits };
|
|
539
|
-
this.resourceLoader = new ResourceLoader(this.limits.maxImageSize);
|
|
540
|
-
}
|
|
541
|
-
}
|
|
542
|
-
export async function createWip(options, limits) {
|
|
543
|
-
const wip = new WIP(limits);
|
|
544
|
-
return wip.create(options);
|
|
545
|
-
}
|
|
546
|
-
export async function verifyWip(wipFile, hash_equal) {
|
|
547
|
-
if (hash_equal !== undefined) {
|
|
548
|
-
const fileHash = wipFile.meta.hash
|
|
549
|
-
.toLowerCase()
|
|
550
|
-
.replace(/^sha256:/, "");
|
|
551
|
-
const expectedHash = hash_equal.toLowerCase().replace(/^sha256:/, "");
|
|
552
|
-
if (fileHash !== expectedHash) {
|
|
553
|
-
return { valid: false, error: "Hash mismatch" };
|
|
554
|
-
}
|
|
555
|
-
}
|
|
556
|
-
const wip = new WIP();
|
|
557
|
-
const result = await wip.verify(wipFile);
|
|
558
|
-
return { valid: result.valid, error: result.error };
|
|
559
|
-
}
|
|
560
|
-
export async function wipToHtml(wipFile, options) {
|
|
561
|
-
const wip = new WIP();
|
|
562
|
-
return wip.toHtml(wipFile, options);
|
|
563
|
-
}
|
|
564
|
-
export async function loadWip(source, limits) {
|
|
565
|
-
const wip = new WIP(limits);
|
|
566
|
-
return wip.load(source);
|
|
567
|
-
}
|
|
568
|
-
export async function generate_wip(options, outputPath) {
|
|
569
|
-
const wip = new WIP(DEFAULT_LIMITS);
|
|
570
|
-
let wipFile = await wip.create({
|
|
571
|
-
text: options.markdown_text,
|
|
572
|
-
textFormat: "markdown",
|
|
573
|
-
images: options.images,
|
|
574
|
-
});
|
|
575
|
-
if (options.account) {
|
|
576
|
-
const { Account } = await import("./account.js");
|
|
577
|
-
const address = await Account.Instance().get_address(options.account);
|
|
578
|
-
if (!address) {
|
|
579
|
-
throw new WipValidationError(`Account not found: ${options.account}`);
|
|
580
|
-
}
|
|
581
|
-
const signature = await Account.Instance().sign(address, wipFile.meta.hash);
|
|
582
|
-
const accountData = await Account.Instance().get(address);
|
|
583
|
-
if (!accountData || !accountData.pubkey) {
|
|
584
|
-
throw new WipValidationError(`Cannot get public key for account: ${address}`);
|
|
585
|
-
}
|
|
586
|
-
let publicKeyBase64;
|
|
587
|
-
if (accountData.pubkey.startsWith("0x")) {
|
|
588
|
-
const buffer = Buffer.from(accountData.pubkey.slice(2), "hex");
|
|
589
|
-
if (buffer.length === 33) {
|
|
590
|
-
publicKeyBase64 = buffer.slice(1).toString("base64");
|
|
591
|
-
}
|
|
592
|
-
else if (buffer.length === 32) {
|
|
593
|
-
publicKeyBase64 = buffer.toString("base64");
|
|
594
|
-
}
|
|
595
|
-
else {
|
|
596
|
-
throw new WipValidationError(`Invalid public key length: ${buffer.length}, expected 32 or 33 bytes`);
|
|
597
|
-
}
|
|
598
|
-
}
|
|
599
|
-
else {
|
|
600
|
-
publicKeyBase64 = accountData.pubkey;
|
|
601
|
-
}
|
|
602
|
-
const signatureBase64 = Buffer.from(signature.slice(2), "hex").toString("base64");
|
|
603
|
-
const newSignature = {
|
|
604
|
-
value: signatureBase64,
|
|
605
|
-
publicKey: publicKeyBase64,
|
|
606
|
-
algorithm: "Ed25519",
|
|
607
|
-
address,
|
|
608
|
-
};
|
|
609
|
-
let signatures;
|
|
610
|
-
if (wipFile.meta.signature) {
|
|
611
|
-
signatures = Array.isArray(wipFile.meta.signature)
|
|
612
|
-
? [...wipFile.meta.signature, newSignature]
|
|
613
|
-
: [wipFile.meta.signature, newSignature];
|
|
614
|
-
}
|
|
615
|
-
else {
|
|
616
|
-
signatures = [newSignature];
|
|
617
|
-
}
|
|
618
|
-
wipFile = {
|
|
619
|
-
...wipFile,
|
|
620
|
-
meta: {
|
|
621
|
-
...wipFile.meta,
|
|
622
|
-
signature: signatures,
|
|
623
|
-
},
|
|
624
|
-
};
|
|
625
|
-
}
|
|
626
|
-
wip.save(wipFile, outputPath, true);
|
|
627
|
-
return outputPath;
|
|
628
|
-
}
|
|
629
|
-
export async function verify_wip(wipFilePath, hash_equal, requireSignature) {
|
|
630
|
-
const wip = new WIP();
|
|
631
|
-
let wipFile;
|
|
632
|
-
try {
|
|
633
|
-
wipFile = await wip.load(wipFilePath);
|
|
634
|
-
}
|
|
635
|
-
catch (error) {
|
|
636
|
-
return {
|
|
637
|
-
valid: false,
|
|
638
|
-
error: `Failed to load WIP file: ${error}`,
|
|
639
|
-
hashValid: false,
|
|
640
|
-
hasSignature: false,
|
|
641
|
-
};
|
|
642
|
-
}
|
|
643
|
-
if (!wipFile.wip || !wipFile.payload || !wipFile.meta) {
|
|
644
|
-
return {
|
|
645
|
-
valid: false,
|
|
646
|
-
error: "Invalid WIP file structure",
|
|
647
|
-
hashValid: false,
|
|
648
|
-
hasSignature: false,
|
|
649
|
-
};
|
|
650
|
-
}
|
|
651
|
-
if (wipFile.meta.type !== "wip") {
|
|
652
|
-
return {
|
|
653
|
-
valid: false,
|
|
654
|
-
error: `Invalid meta.type: ${wipFile.meta.type}`,
|
|
655
|
-
hashValid: false,
|
|
656
|
-
hasSignature: !!wipFile.meta.signature,
|
|
657
|
-
};
|
|
658
|
-
}
|
|
659
|
-
if (hash_equal !== undefined) {
|
|
660
|
-
const fileHash = wipFile.meta.hash
|
|
661
|
-
.toLowerCase()
|
|
662
|
-
.replace(/^sha256:/, "");
|
|
663
|
-
const expectedHash = hash_equal.toLowerCase().replace(/^sha256:/, "");
|
|
664
|
-
if (fileHash !== expectedHash) {
|
|
665
|
-
return {
|
|
666
|
-
valid: false,
|
|
667
|
-
error: "Hash mismatch",
|
|
668
|
-
hashValid: false,
|
|
669
|
-
hasSignature: !!wipFile.meta.signature,
|
|
670
|
-
};
|
|
671
|
-
}
|
|
672
|
-
}
|
|
673
|
-
if (requireSignature && !wipFile.meta.signature) {
|
|
674
|
-
return {
|
|
675
|
-
valid: false,
|
|
676
|
-
error: "Signature required but WIP file has no signature",
|
|
677
|
-
hashValid: true,
|
|
678
|
-
hasSignature: false,
|
|
679
|
-
};
|
|
680
|
-
}
|
|
681
|
-
const canonicalPayload = canonicalizeJson(wipFile.payload);
|
|
682
|
-
const computedHash = computeHash(canonicalPayload);
|
|
683
|
-
const hashValid = computedHash === wipFile.meta.hash;
|
|
684
|
-
if (!hashValid) {
|
|
685
|
-
return {
|
|
686
|
-
valid: false,
|
|
687
|
-
error: "Hash mismatch - content has been tampered",
|
|
688
|
-
hashValid: false,
|
|
689
|
-
hasSignature: !!wipFile.meta.signature,
|
|
690
|
-
};
|
|
691
|
-
}
|
|
692
|
-
let signatureValid;
|
|
693
|
-
const signatures = [];
|
|
694
|
-
if (wipFile.meta.signature) {
|
|
695
|
-
const sigArray = Array.isArray(wipFile.meta.signature)
|
|
696
|
-
? wipFile.meta.signature
|
|
697
|
-
: [wipFile.meta.signature];
|
|
698
|
-
let allValid = true;
|
|
699
|
-
for (const sig of sigArray) {
|
|
700
|
-
const isValid = await wip["verifySignature"](wipFile.meta.hash, sig.value, sig.publicKey, sig.algorithm);
|
|
701
|
-
let address;
|
|
702
|
-
try {
|
|
703
|
-
const { Ed25519PublicKey } = await import("../../keypairs/ed25519/publickey.js");
|
|
704
|
-
const pubKey = new Ed25519PublicKey(sig.publicKey);
|
|
705
|
-
address = pubKey.toWAddress();
|
|
706
|
-
}
|
|
707
|
-
catch {
|
|
708
|
-
}
|
|
709
|
-
signatures.push({
|
|
710
|
-
publicKey: sig.publicKey,
|
|
711
|
-
address,
|
|
712
|
-
valid: isValid,
|
|
713
|
-
});
|
|
714
|
-
if (!isValid) {
|
|
715
|
-
allValid = false;
|
|
716
|
-
}
|
|
717
|
-
}
|
|
718
|
-
signatureValid = allValid;
|
|
719
|
-
if (!signatureValid) {
|
|
720
|
-
const failedAddresses = signatures
|
|
721
|
-
.filter((s) => !s.valid && s.address)
|
|
722
|
-
.map((s) => s.address);
|
|
723
|
-
return {
|
|
724
|
-
valid: false,
|
|
725
|
-
error: `Signatures from the following addresses are invalid: ${failedAddresses.join(", ")}`,
|
|
726
|
-
hashValid: true,
|
|
727
|
-
signatureValid: false,
|
|
728
|
-
hasSignature: true,
|
|
729
|
-
signatures,
|
|
730
|
-
};
|
|
731
|
-
}
|
|
732
|
-
}
|
|
733
|
-
return {
|
|
734
|
-
valid: true,
|
|
735
|
-
hashValid: true,
|
|
736
|
-
signatureValid,
|
|
737
|
-
hasSignature: !!wipFile.meta.signature,
|
|
738
|
-
signatures: signatures.length > 0 ? signatures : undefined,
|
|
739
|
-
};
|
|
740
|
-
}
|
|
741
|
-
export async function sign_wip(wipFilePath, account, outputPath) {
|
|
742
|
-
const wip = new WIP();
|
|
743
|
-
const wipFile = await wip.load(wipFilePath);
|
|
744
|
-
if (!wipFile.wip || !wipFile.payload || !wipFile.meta) {
|
|
745
|
-
throw new WipValidationError("Invalid WIP file structure");
|
|
746
|
-
}
|
|
747
|
-
if (wipFile.meta.type !== "wip") {
|
|
748
|
-
throw new WipValidationError(`Invalid meta.type: ${wipFile.meta.type}`);
|
|
749
|
-
}
|
|
750
|
-
const { Account } = await import("./account.js");
|
|
751
|
-
const address = await Account.Instance().get_address(account);
|
|
752
|
-
if (!address) {
|
|
753
|
-
throw new WipValidationError(`Account not found: ${account}`);
|
|
754
|
-
}
|
|
755
|
-
const signResult = await Account.Instance().signData(address, wipFile.meta.hash);
|
|
756
|
-
let publicKeyBase64;
|
|
757
|
-
const pk = signResult.publicKey;
|
|
758
|
-
if (pk.startsWith("0x")) {
|
|
759
|
-
const buffer = Buffer.from(pk.slice(2), "hex");
|
|
760
|
-
if (buffer.length === 33) {
|
|
761
|
-
publicKeyBase64 = buffer.slice(1).toString("base64");
|
|
762
|
-
}
|
|
763
|
-
else if (buffer.length === 32) {
|
|
764
|
-
publicKeyBase64 = buffer.toString("base64");
|
|
765
|
-
}
|
|
766
|
-
else {
|
|
767
|
-
throw new WipValidationError(`Invalid public key length: ${buffer.length}, expected 32 or 33 bytes`);
|
|
768
|
-
}
|
|
769
|
-
}
|
|
770
|
-
else {
|
|
771
|
-
publicKeyBase64 = pk;
|
|
772
|
-
}
|
|
773
|
-
const newSignature = {
|
|
774
|
-
value: Buffer.from(signResult.signature.slice(2), "hex").toString("base64"),
|
|
775
|
-
publicKey: publicKeyBase64,
|
|
776
|
-
algorithm: "Ed25519",
|
|
777
|
-
address: signResult.address,
|
|
778
|
-
};
|
|
779
|
-
let signatures;
|
|
780
|
-
if (wipFile.meta.signature) {
|
|
781
|
-
const existingSigs = Array.isArray(wipFile.meta.signature)
|
|
782
|
-
? [...wipFile.meta.signature]
|
|
783
|
-
: [wipFile.meta.signature];
|
|
784
|
-
const existingIndex = existingSigs.findIndex((sig) => sig.publicKey === publicKeyBase64);
|
|
785
|
-
if (existingIndex >= 0) {
|
|
786
|
-
existingSigs[existingIndex] = newSignature;
|
|
787
|
-
signatures = existingSigs;
|
|
788
|
-
}
|
|
789
|
-
else {
|
|
790
|
-
signatures = [...existingSigs, newSignature];
|
|
791
|
-
}
|
|
792
|
-
}
|
|
793
|
-
else {
|
|
794
|
-
signatures = [newSignature];
|
|
795
|
-
}
|
|
796
|
-
const signedWipFile = {
|
|
797
|
-
...wipFile,
|
|
798
|
-
meta: {
|
|
799
|
-
...wipFile.meta,
|
|
800
|
-
signature: signatures,
|
|
801
|
-
},
|
|
802
|
-
};
|
|
803
|
-
let savePath;
|
|
804
|
-
if (outputPath) {
|
|
805
|
-
savePath = outputPath;
|
|
806
|
-
}
|
|
807
|
-
else {
|
|
808
|
-
const dir = path.dirname(wipFilePath);
|
|
809
|
-
const ext = path.extname(wipFilePath);
|
|
810
|
-
const baseName = path.basename(wipFilePath, ext);
|
|
811
|
-
savePath = path.join(dir, `signed_${baseName}${ext}`);
|
|
812
|
-
}
|
|
813
|
-
wip.save(signedWipFile, savePath, true);
|
|
814
|
-
return savePath;
|
|
815
|
-
}
|
|
816
|
-
export async function wip2html(wipPath, options = {}) {
|
|
817
|
-
const fs = await import("fs");
|
|
818
|
-
const path = await import("path");
|
|
819
|
-
const stats = fs.statSync(wipPath);
|
|
820
|
-
if (stats.isFile()) {
|
|
821
|
-
const wip = new WIP();
|
|
822
|
-
const wipFile = await wip.load(wipPath);
|
|
823
|
-
const html = await wip.toHtml(wipFile, options);
|
|
824
|
-
if (options.outputPath) {
|
|
825
|
-
fs.writeFileSync(options.outputPath, html);
|
|
826
|
-
return options.outputPath;
|
|
827
|
-
}
|
|
828
|
-
const dir = path.dirname(wipPath);
|
|
829
|
-
const ext = path.extname(wipPath);
|
|
830
|
-
const baseName = path.basename(wipPath, ext);
|
|
831
|
-
const outputFilePath = path.join(dir, `${baseName}.html`);
|
|
832
|
-
fs.writeFileSync(outputFilePath, html);
|
|
833
|
-
return outputFilePath;
|
|
834
|
-
}
|
|
835
|
-
else if (stats.isDirectory()) {
|
|
836
|
-
const files = fs.readdirSync(wipPath);
|
|
837
|
-
const wipFiles = files.filter((f) => f.endsWith(".wip"));
|
|
838
|
-
if (wipFiles.length === 0) {
|
|
839
|
-
throw new WipValidationError(`No .wip files found in directory: ${wipPath}`);
|
|
840
|
-
}
|
|
841
|
-
const results = [];
|
|
842
|
-
const wip = new WIP();
|
|
843
|
-
for (const file of wipFiles) {
|
|
844
|
-
const filePath = path.join(wipPath, file);
|
|
845
|
-
const wipFile = await wip.load(filePath);
|
|
846
|
-
const html = await wip.toHtml(wipFile, options);
|
|
847
|
-
const outputFileName = file.replace(".wip", ".html");
|
|
848
|
-
const outputFilePath = options.outputPath
|
|
849
|
-
? path.join(options.outputPath, outputFileName)
|
|
850
|
-
: path.join(wipPath, outputFileName);
|
|
851
|
-
const outputDir = path.dirname(outputFilePath);
|
|
852
|
-
if (!fs.existsSync(outputDir)) {
|
|
853
|
-
fs.mkdirSync(outputDir, { recursive: true });
|
|
854
|
-
}
|
|
855
|
-
fs.writeFileSync(outputFilePath, html);
|
|
856
|
-
results.push(outputFilePath);
|
|
857
|
-
}
|
|
858
|
-
return results;
|
|
859
|
-
}
|
|
860
|
-
else {
|
|
861
|
-
throw new WipValidationError(`Invalid path: ${wipPath}`);
|
|
862
|
-
}
|
|
863
|
-
}
|
|
864
|
-
export default WIP;
|
|
1
|
+
import{sha256}from'@noble/hashes/sha256';import{bytesToHex}from'@noble/hashes/utils';import*as a178a from'fs';import*as a178b from'path';import*as a178c from'https';import*as a178d from'http';const WIP_SCHEMA_URL='https://schema.wowok.net/wip/v1',WIP_VERSION='1.0.0';export const DEFAULT_LIMITS={'maxImageSize':0x2*0x400*0x400,'maxTotalSize':0xa*0x400*0x400,'maxImageCount':0xa,'maxTextLength':0x2710};export class WipError extends Error{constructor(a){super(a),this['name']='WipError';}}export class WipValidationError extends WipError{constructor(a){super(a),this['name']='WipValidationError';}}export class WipSizeError extends WipError{constructor(a){super(a),this['name']='WipSizeError';}}function detectMimeType(a){if(a['length']>=0x4&&a[0x0]===0x89&&a[0x1]===0x50&&a[0x2]===0x4e&&a[0x3]===0x47)return'image/png';if(a['length']>=0x3&&a[0x0]===0xff&&a[0x1]===0xd8&&a[0x2]===0xff)return'image/jpeg';if(a['length']>=0x6&&a[0x0]===0x47&&a[0x1]===0x49&&a[0x2]===0x46)return'image/gif';if(a['length']>=0xc&&a[0x0]===0x52&&a[0x1]===0x49&&a[0x2]===0x46&&a[0x3]===0x46&&a[0x8]===0x57&&a[0x9]===0x45&&a[0xa]===0x42&&a[0xb]===0x50)return'image/webp';return null;}function uint8ArrayToBase64(a){let b='';const c=a['length'];for(let d=0x0;d<c;d++){b+=String['fromCharCode'](a[d]);}return btoa(b);}function base64ToUint8Array(a){const b=atob(a),c=b['length'],d=new Uint8Array(c);for(let e=0x0;e<c;e++){d[e]=b['charCodeAt'](e);}return d;}function canonicalizeJson(a){if(a===null||typeof a!=='object')return JSON['stringify'](a);if(Array['isArray'](a))return'['+a['map'](canonicalizeJson)['join'](',')+']';const b=a,c=Object['keys'](b)['sort'](),d=c['map'](e=>'\x22'+e+'\x22:'+canonicalizeJson(b[e]));return'{'+d['join'](',')+'}';}function computeHash(a){const b=sha256(new TextEncoder()['encode'](a));return bytesToHex(b);}function generateId(a){const b=Date['now']()['toString'](0x24),c=Math['random']()['toString'](0x24)['substring'](0x2,0x8);return a+'-'+b+'-'+c;}function getExtensionFromMimeType(a){const b={'image/png':'png','image/jpeg':'jpg','image/gif':'gif','image/webp':'webp'};return b[a]||'bin';}class ResourceLoader{['maxSize'];constructor(a){this['maxSize']=a;}async['load'](a){if(!a||a['trim']()==='')throw new WipError('WIP\x20file\x20path\x20cannot\x20be\x20empty');if(a['startsWith']('data:'))return this['loadFromDataUrl'](a);if(a['startsWith']('http://')||a['startsWith']('https://'))return this['loadFromNetwork'](a);return this['loadFromFile'](a);}['loadFromDataUrl'](a){const b=a['match'](/^data:image\/(\w+);base64,(.+)$/);if(!b)throw new WipValidationError('Invalid\x20data\x20URL\x20format:\x20'+a['substring'](0x0,0x32)+'...');const c=b[0x2];try{return base64ToUint8Array(c);}catch(d){throw new WipError('Failed\x20to\x20decode\x20data\x20URL:\x20'+d);}}async['loadFromNetwork'](a){return new Promise((b,c)=>{const d=setTimeout(()=>{c(new WipError('Network\x20timeout\x20while\x20fetching:\x20'+a));},0x7530),e=a['startsWith']('https:'),f=e?a178c:a178d,g={'headers':{'Accept':'application/json,*/*'}};e&&(g['rejectUnauthorized']=![]);const h=f['get'](a,g,i=>{clearTimeout(d);if(i['statusCode']!==0xc8){c(new WipError('Failed\x20to\x20fetch:\x20'+i['statusCode']+'\x20'+i['statusMessage']));return;}const j=i['headers']['content-length'];if(j&&parseInt(j)>this['maxSize']){c(new WipSizeError('Resource\x20from\x20'+a+'\x20size\x20('+j+'\x20bytes)\x20exceeds\x20limit\x20('+this['maxSize']+'\x20bytes)'));return;}const k=[];i['on']('data',l=>{k['push'](l);}),i['on']('end',()=>{const l=Buffer['concat'](k);if(l['length']>this['maxSize']){c(new WipSizeError('Resource\x20from\x20'+a+'\x20size\x20('+l['length']+'\x20bytes)\x20exceeds\x20limit\x20('+this['maxSize']+'\x20bytes)'));return;}b(new Uint8Array(l));}),i['on']('error',l=>{c(new WipError('Network\x20error:\x20'+l['message']));});});h['on']('error',i=>{clearTimeout(d),c(new WipError('Network\x20error:\x20'+i['message']));});});}['loadFromFile'](a){const b=a178b['resolve'](a);if(!a178a['existsSync'](b))throw new WipError('File\x20not\x20found:\x20'+b);const c=a178a['statSync'](b);if(!c['isFile']())throw new WipError('Path\x20is\x20not\x20a\x20file:\x20'+b);if(c['size']>this['maxSize'])throw new WipSizeError('File\x20'+b+'\x20size\x20('+c['size']+'\x20bytes)\x20exceeds\x20limit\x20('+this['maxSize']+'\x20bytes)');const d=a178a['readFileSync'](b);return new Uint8Array(d);}}export class WIP{['limits'];['resourceLoader'];constructor(a={}){this['limits']={...DEFAULT_LIMITS,...a},this['resourceLoader']=new ResourceLoader(this['limits']['maxImageSize']);}async['create'](a){if(a['text']['length']>this['limits']['maxTextLength'])throw new WipSizeError('Text\x20length\x20('+a['text']['length']+')\x20exceeds\x20limit\x20('+this['limits']['maxTextLength']+')');const b=[];if(a['images']&&a['images']['length']>0x0){if(a['images']['length']>this['limits']['maxImageCount'])throw new WipSizeError('Image\x20count\x20('+a['images']['length']+')\x20exceeds\x20limit\x20('+this['limits']['maxImageCount']+')');for(let j=0x0;j<a['images']['length'];j++){const k=await this['processImage'](a['images'][j],j);b['push'](k);}}const c={'content':{'text':a['text'],'format':a['textFormat']||'plain'},'media':b},d=canonicalizeJson(c),e=computeHash(d),f={'type':'wip','version':WIP_VERSION,'created':new Date()['toISOString'](),'hash':e,'algorithm':'sha256'};if(a['signKeyPair']){const l=await this['sign'](e,a['signKeyPair']['privateKey'],a['signAlgorithm']||'Ed25519');f['signature']={'value':l,'publicKey':a['signKeyPair']['publicKey'],'algorithm':a['signAlgorithm']||'Ed25519'};}const g={'wip':WIP_SCHEMA_URL,'payload':c,'meta':f},h=JSON['stringify'](g);if(h['length']>this['limits']['maxTotalSize'])throw new WipSizeError('Total\x20WIP\x20file\x20size\x20('+h['length']+'\x20bytes)\x20exceeds\x20limit\x20('+this['limits']['maxTotalSize']+'\x20bytes)');return g;}async['processImage'](a,b){const c=await this['resourceLoader']['load'](a['source']),d=detectMimeType(c);if(!d)throw new WipValidationError('Unsupported\x20image\x20format:\x20'+a['source']);let e=a['filename'];if(!e){if(a['source']['startsWith']('http')){const f=new URL(a['source']),g=f['pathname'];e=g['substring'](g['lastIndexOf']('/')+0x1)||'image-'+b;}else e=a['source']['substring'](a['source']['lastIndexOf']('/')+0x1)||'image-'+b;}return{'id':a['id']||generateId('img'),'type':d,'data':uint8ArrayToBase64(c),'filename':e};}async['sign'](a,b,c){if(c!=='Ed25519')throw new WipError('Unsupported\x20signature\x20algorithm:\x20'+c);const {Ed25519Keypair:d}=await import('../../keypairs/ed25519/index.js'),e=d['fromSecretKey'](b),f=await e['sign'](new TextEncoder()['encode'](a));return uint8ArrayToBase64(f);}async['verify'](a){try{if(!a['wip']||!a['payload']||!a['meta'])return{'valid':![],'error':'Invalid\x20WIP\x20file\x20structure'};if(a['meta']['type']!=='wip')return{'valid':![],'error':'Invalid\x20meta.type:\x20'+a['meta']['type']};const b=canonicalizeJson(a['payload']),c=computeHash(b);if(c!==a['meta']['hash'])return{'valid':![],'error':'Hash\x20mismatch\x20-\x20content\x20has\x20been\x20tampered'};const d=[];if(a['meta']['signature']){const e=Array['isArray'](a['meta']['signature'])?a['meta']['signature']:[a['meta']['signature']];for(const f of e){const g=await this['verifySignature'](a['meta']['hash'],f['value'],f['publicKey'],f['algorithm']);d['push']({'address':f['address'],'valid':g});if(!g)return{'valid':![],'error':'Invalid\x20signature','signatures':d};}}return{'valid':!![],'signatures':d};}catch(h){return{'valid':![],'error':'Verification\x20error:\x20'+h};}}async['verifySignature'](a,b,c,d){if(d!=='Ed25519')throw new WipError('Unsupported\x20signature\x20algorithm:\x20'+d);try{const {Ed25519PublicKey:e}=await import('../../keypairs/ed25519/publickey.js');let f=c;if(c['startsWith']('0x')){const i=Buffer['from'](c['slice'](0x2),'hex');if(i['length']===0x21)f=i['slice'](0x1)['toString']('base64');else i['length']===0x20&&(f=i['toString']('base64'));}else try{const j=Buffer['from'](c,'base64');j['length']===0x21&&(f=j['slice'](0x1)['toString']('base64'));}catch{}const g=new e(f),h=Uint8Array['from'](Buffer['from'](b,'base64'));return await g['verify'](new TextEncoder()['encode'](a),h);}catch(k){return console['error']('Signature\x20verification\x20error:',k),![];}}async['toHtml'](a,b={}){const {title:title='WIP\x20Document',theme:theme='light'}=b,{payload:c,meta:d}=a,e=o=>{return o['replace'](/&/g,'&')['replace'](/</g,'<')['replace'](/>/g,'>')['replace'](/"/g,'"')['replace'](/'/g,''');},f=(o,p)=>{switch(p){case'html':return o;case'markdown':return o['replace'](/\*\*(.+?)\*\*/g,'<strong>$1</strong>')['replace'](/\*(.+?)\*/g,'<em>$1</em>')['replace'](/\n/g,'<br>');case'plain':default:return e(o)['replace'](/\n/g,'<br>');}},g=theme==='dark'?'#1a1a1a':'#ffffff',h=theme==='dark'?'#e0e0e0':'#333333',i=theme==='dark'?'#444444':'#e0e0e0',j='#4caf50',k='#ff9800',l=await this['verify'](a),m=l['valid']?'<span\x20style=\x22background:\x20'+j+';\x20color:\x20white;\x20padding:\x204px\x208px;\x20border-radius:\x204px;\x20font-size:\x2012px;\x22>✓\x20Verified</span>':'<span\x20style=\x22background:\x20'+k+';\x20color:\x20white;\x20padding:\x204px\x208px;\x20border-radius:\x204px;\x20font-size:\x2012px;\x22>⚠\x20Tampered</span>',n=c['media']['map'](o=>'\x0a\x09\x09\x09\x09<div\x20style=\x22margin:\x2016px\x200;\x20border:\x201px\x20solid\x20'+i+';\x20border-radius:\x208px;\x20overflow:\x20hidden;\x22>\x0a\x09\x09\x09\x09\x09<img\x20src=\x22data:'+o['type']+';base64,'+o['data']+'\x22\x20\x0a\x09\x09\x09\x09\x09\x20\x20\x20\x20\x20style=\x22max-width:\x20100%;\x20height:\x20auto;\x20display:\x20block;\x22\x20\x0a\x09\x09\x09\x09\x09\x20\x20\x20\x20\x20alt=\x22'+e(o['filename']||o['id'])+'\x22\x20/>\x0a\x09\x09\x09\x09\x09'+(o['filename']?'<div\x20style=\x22padding:\x208px;\x20font-size:\x2012px;\x20color:\x20#666;\x20background:\x20'+(theme==='dark'?'#2a2a2a':'#f5f5f5')+';\x20border-top:\x201px\x20solid\x20'+i+';\x22>'+e(o['filename'])+'</div>':'')+'\x0a\x09\x09\x09\x09</div>\x0a\x09\x09\x09')['join']('');return'<!DOCTYPE\x20html>\x0a<html\x20lang=\x22en\x22>\x0a<head>\x0a\x20\x20\x20\x20<meta\x20charset=\x22UTF-8\x22>\x0a\x20\x20\x20\x20<meta\x20name=\x22viewport\x22\x20content=\x22width=device-width,\x20initial-scale=1.0\x22>\x0a\x20\x20\x20\x20<title>'+e(title)+'</title>\x0a</head>\x0a<body\x20style=\x22margin:\x200;\x20padding:\x2020px;\x20font-family:\x20-apple-system,\x20BlinkMacSystemFont,\x20\x27Segoe\x20UI\x27,\x20Roboto,\x20sans-serif;\x20background:\x20'+g+';\x20color:\x20'+h+';\x20line-height:\x201.6;\x22>\x0a\x20\x20\x20\x20<div\x20style=\x22max-width:\x20800px;\x20margin:\x200\x20auto;\x20background:\x20'+(theme==='dark'?'#252525':'#ffffff')+';\x20border-radius:\x2012px;\x20box-shadow:\x200\x202px\x208px\x20rgba(0,0,0,0.1);\x20overflow:\x20hidden;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22padding:\x2020px\x2024px;\x20border-bottom:\x201px\x20solid\x20'+i+';\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22display:\x20flex;\x20justify-content:\x20space-between;\x20align-items:\x20center;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<h1\x20style=\x22margin:\x200;\x20font-size:\x2020px;\x20font-weight:\x20600;\x22>'+e(title)+'</h1>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22font-size:\x2012px;\x20color:\x20#666;\x20margin-top:\x204px;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20WIP\x20v'+d['version']+'\x20•\x20'+new Date(d['created'])['toLocaleString']()+'\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'+m+'\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22font-size:\x2011px;\x20color:\x20#999;\x20margin-top:\x2012px;\x20padding:\x208px;\x20background:\x20'+(theme==='dark'?'#2a2a2a':'#f5f5f5')+';\x20border-radius:\x204px;\x20font-style:\x20italic;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20Important\x20Note:\x20This\x20page\x20is\x20for\x20document\x20browsing\x20and\x20verification\x20reference\x20only.\x20Please\x20verify\x20the\x20document\x20integrity\x20through\x20the\x20API\x20using\x20the\x20WIP\x20file.\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'+(l['signatures']&&l['signatures']['length']>0x0?'\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22margin-top:\x2012px;\x20padding:\x208px;\x20background:\x20'+(theme==='dark'?'#2a3f2a':'#e8f5e9')+';\x20border-radius:\x204px;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22font-size:\x2011px;\x20color:\x20'+(theme==='dark'?'#81c784':'#2e7d32')+';\x20margin-bottom:\x204px;\x22>✓\x20Signature\x20Verification\x20('+l['signatures']['length']+'\x20signature'+(l['signatures']['length']>0x1?'s':'')+')</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'+l['signatures']['map']((o,p)=>'\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22font-size:\x2010px;\x20color:\x20'+h+';\x20margin-left:\x208px;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'+(p+0x1)+'.\x20'+(o['address']?e(o['address']['slice'](0x0,0x14))+'...':'Unknown')+':\x20'+(o['valid']?'<span\x20style=\x22color:\x20#4caf50;\x22>✓\x20Valid</span>':'<span\x20style=\x22color:\x20#f44336;\x22>✗\x20Invalid</span>')+'\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20')['join']('')+'\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20':'')+'\x0a\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22padding:\x2024px;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22font-size:\x2016px;\x20line-height:\x201.8;\x20margin-bottom:\x2024px;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'+f(c['content']['text'],c['content']['format'])+'\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'+n+'\x0a\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22padding:\x2016px\x2024px;\x20background:\x20'+(theme==='dark'?'#2a2a2a':'#f8f9fa')+';\x20border-top:\x201px\x20solid\x20'+i+';\x20font-size:\x2011px;\x20color:\x20#666;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22display:\x20flex;\x20justify-content:\x20space-between;\x20align-items:\x20center;\x20flex-wrap:\x20wrap;\x20gap:\x208px;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<strong>Hash:</strong>\x20<code\x20style=\x22background:\x20'+(theme==='dark'?'#333':'#e9ecef')+';\x20padding:\x202px\x206px;\x20border-radius:\x203px;\x22>'+e(d['hash'])+'</code>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'+(l['valid']?'Content\x20integrity\x20verified':'Verification\x20failed:\x20'+e(l['error']||'Unknown\x20error'))+'\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20</div>\x0a</body>\x0a</html>';}['stringify'](a,b=!![]){return b?JSON['stringify'](a,null,0x2):JSON['stringify'](a);}['parse'](a){try{const b=JSON['parse'](a);if(!b['wip']||!b['payload']||!b['meta'])throw new WipValidationError('Invalid\x20WIP\x20file\x20structure');return b;}catch(c){if(c instanceof WipError)throw c;throw new WipValidationError('Failed\x20to\x20parse\x20WIP\x20file:\x20'+c);}}async['load'](a){const b=await this['resourceLoader']['load'](a),c=new TextDecoder()['decode'](b);return this['parse'](c);}['getHash'](a){const b=a['meta']['hash'];if(b['includes'](':'))return b['split'](':')[0x1];return b;}['extractImages'](a,b){!a178a['existsSync'](b)&&a178a['mkdirSync'](b,{'recursive':!![]});const c=[];for(const d of a['payload']['media']){const e=getExtensionFromMimeType(d['type']),f=d['filename']||d['id']+'.'+e,g=a178b['join'](b,f),h=Buffer['from'](base64ToUint8Array(d['data']));a178a['writeFileSync'](g,h),c['push'](g);}return c;}['save'](a,b,c=!![]){const d=a178b['dirname'](b);!a178a['existsSync'](d)&&a178a['mkdirSync'](d,{'recursive':!![]}),a178a['writeFileSync'](b,this['stringify'](a,c),'utf-8');}['getLimits'](){return{...this['limits']};}['setLimits'](a){this['limits']={...this['limits'],...a},this['resourceLoader']=new ResourceLoader(this['limits']['maxImageSize']);}}export async function createWip(a,b){const c=new WIP(b);return c['create'](a);}export async function verifyWip(a,b){if(b!==undefined){const e=a['meta']['hash']['toLowerCase']()['replace'](/^sha256:/,''),f=b['toLowerCase']()['replace'](/^sha256:/,'');if(e!==f)return{'valid':![],'error':'Hash\x20mismatch'};}const c=new WIP(),d=await c['verify'](a);return{'valid':d['valid'],'error':d['error']};}export async function wipToHtml(a,b){const c=new WIP();return c['toHtml'](a,b);}export async function loadWip(a,b){const c=new WIP(b);return c['load'](a);}export async function generate_wip(a,b){const c=new WIP(DEFAULT_LIMITS);let d=await c['create']({'text':a['markdown_text'],'textFormat':'markdown','images':a['images']});if(a['account']){const {Account:e}=await import('./account.js'),f=await e['Instance']()['get_address'](a['account']);if(!f)throw new WipValidationError('Account\x20not\x20found:\x20'+a['account']);const g=await e['Instance']()['sign'](f,d['meta']['hash']),h=await e['Instance']()['get'](f);if(!h||!h['pubkey'])throw new WipValidationError('Cannot\x20get\x20public\x20key\x20for\x20account:\x20'+f);let i;if(h['pubkey']['startsWith']('0x')){const m=Buffer['from'](h['pubkey']['slice'](0x2),'hex');if(m['length']===0x21)i=m['slice'](0x1)['toString']('base64');else{if(m['length']===0x20)i=m['toString']('base64');else throw new WipValidationError('Invalid\x20public\x20key\x20length:\x20'+m['length']+',\x20expected\x2032\x20or\x2033\x20bytes');}}else i=h['pubkey'];const j=Buffer['from'](g['slice'](0x2),'hex')['toString']('base64'),k={'value':j,'publicKey':i,'algorithm':'Ed25519','address':f};let l;d['meta']['signature']?l=Array['isArray'](d['meta']['signature'])?[...d['meta']['signature'],k]:[d['meta']['signature'],k]:l=[k],d={...d,'meta':{...d['meta'],'signature':l}};}return c['save'](d,b,!![]),b;}export async function verify_wip(a,b,c){const d=new WIP();let e;try{e=await d['load'](a);}catch(k){return{'valid':![],'error':'Failed\x20to\x20load\x20WIP\x20file:\x20'+k,'hashValid':![],'hasSignature':![]};}if(!e['wip']||!e['payload']||!e['meta'])return{'valid':![],'error':'Invalid\x20WIP\x20file\x20structure','hashValid':![],'hasSignature':![]};if(e['meta']['type']!=='wip')return{'valid':![],'error':'Invalid\x20meta.type:\x20'+e['meta']['type'],'hashValid':![],'hasSignature':!!e['meta']['signature']};if(b!==undefined){const l=e['meta']['hash']['toLowerCase']()['replace'](/^sha256:/,''),m=b['toLowerCase']()['replace'](/^sha256:/,'');if(l!==m)return{'valid':![],'error':'Hash\x20mismatch','hashValid':![],'hasSignature':!!e['meta']['signature']};}if(c&&!e['meta']['signature'])return{'valid':![],'error':'Signature\x20required\x20but\x20WIP\x20file\x20has\x20no\x20signature','hashValid':!![],'hasSignature':![]};const f=canonicalizeJson(e['payload']),g=computeHash(f),h=g===e['meta']['hash'];if(!h)return{'valid':![],'error':'Hash\x20mismatch\x20-\x20content\x20has\x20been\x20tampered','hashValid':![],'hasSignature':!!e['meta']['signature']};let i;const j=[];if(e['meta']['signature']){const n=Array['isArray'](e['meta']['signature'])?e['meta']['signature']:[e['meta']['signature']];let o=!![];for(const p of n){const q=await d['verifySignature'](e['meta']['hash'],p['value'],p['publicKey'],p['algorithm']);let r;try{const {Ed25519PublicKey:s}=await import('../../keypairs/ed25519/publickey.js'),t=new s(p['publicKey']);r=t['toWAddress']();}catch{}j['push']({'publicKey':p['publicKey'],'address':r,'valid':q}),!q&&(o=![]);}i=o;if(!i){const u=j['filter'](v=>!v['valid']&&v['address'])['map'](v=>v['address']);return{'valid':![],'error':'Signatures\x20from\x20the\x20following\x20addresses\x20are\x20invalid:\x20'+u['join'](',\x20'),'hashValid':!![],'signatureValid':![],'hasSignature':!![],'signatures':j};}}return{'valid':!![],'hashValid':!![],'signatureValid':i,'hasSignature':!!e['meta']['signature'],'signatures':j['length']>0x0?j:undefined};}export async function sign_wip(a,b,c){const d=new WIP(),e=await d['load'](a);if(!e['wip']||!e['payload']||!e['meta'])throw new WipValidationError('Invalid\x20WIP\x20file\x20structure');if(e['meta']['type']!=='wip')throw new WipValidationError('Invalid\x20meta.type:\x20'+e['meta']['type']);const {Account:f}=await import('./account.js'),g=await f['Instance']()['get_address'](b);if(!g)throw new WipValidationError('Account\x20not\x20found:\x20'+b);const h=await f['Instance']()['signData'](g,e['meta']['hash']);let i;const j=h['publicKey'];if(j['startsWith']('0x')){const o=Buffer['from'](j['slice'](0x2),'hex');if(o['length']===0x21)i=o['slice'](0x1)['toString']('base64');else{if(o['length']===0x20)i=o['toString']('base64');else throw new WipValidationError('Invalid\x20public\x20key\x20length:\x20'+o['length']+',\x20expected\x2032\x20or\x2033\x20bytes');}}else i=j;const k={'value':Buffer['from'](h['signature']['slice'](0x2),'hex')['toString']('base64'),'publicKey':i,'algorithm':'Ed25519','address':h['address']};let l;if(e['meta']['signature']){const p=Array['isArray'](e['meta']['signature'])?[...e['meta']['signature']]:[e['meta']['signature']],q=p['findIndex'](r=>r['publicKey']===i);q>=0x0?(p[q]=k,l=p):l=[...p,k];}else l=[k];const m={...e,'meta':{...e['meta'],'signature':l}};let n;if(c)n=c;else{const r=a178b['dirname'](a),s=a178b['extname'](a),t=a178b['basename'](a,s);n=a178b['join'](r,'signed_'+t+s);}return d['save'](m,n,!![]),n;}export async function wip2html(a,b={}){const c=await import('fs'),d=await import('path'),e=c['statSync'](a);if(e['isFile']()){const f=new WIP(),g=await f['load'](a),h=await f['toHtml'](g,b);if(b['outputPath'])return c['writeFileSync'](b['outputPath'],h),b['outputPath'];const i=d['dirname'](a),j=d['extname'](a),k=d['basename'](a,j),l=d['join'](i,k+'.html');return c['writeFileSync'](l,h),l;}else{if(e['isDirectory']()){const m=c['readdirSync'](a),n=m['filter'](q=>q['endsWith']('.wip'));if(n['length']===0x0)throw new WipValidationError('No\x20.wip\x20files\x20found\x20in\x20directory:\x20'+a);const o=[],p=new WIP();for(const q of n){const r=d['join'](a,q),s=await p['load'](r),t=await p['toHtml'](s,b),u=q['replace']('.wip','.html'),v=b['outputPath']?d['join'](b['outputPath'],u):d['join'](a,u),w=d['dirname'](v);!c['existsSync'](w)&&c['mkdirSync'](w,{'recursive':!![]}),c['writeFileSync'](v,t),o['push'](v);}return o;}else throw new WipValidationError('Invalid\x20path:\x20'+a);}}export default WIP;
|