Feat/1285 es ucan formatting (#1302)

* feat: Add Enclave Usage Examples

* feat(es/ucan): Add comprehensive integration tests

- Create integration.test.ts with full UCAN token lifecycle testing
- Cover end-to-end token creation, parsing, and validation
- Test capability attenuation and delegation chains
- Validate multi-algorithm support and timestamp scenarios
- Implement error recovery and performance test scenarios

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>

* No commit suggestions generated

* No commit suggestions generated

* chore: Remove migrated components and add migration documentation

Removed all code and references for components that have been moved to separate repositories:

**Moved to sonr-io/hway:**
- bridge/ - HTTP service with OAuth2/OIDC/WebAuthn handlers
- cmd/hway/ - Highway service binary
- internal/migrations/ - PostgreSQL schema migrations

**Moved to sonr-io/motr:**
- cmd/motr/ - Motor worker service (WASM vault operations)
- cmd/vault/ - Vault CLI tool
- crypto/ - Comprehensive cryptographic library
- packages/ - TypeScript SDK packages (es, sdk, ui, com, pkl)
- web/auth/ - Authentication web application
- web/dash/ - Dashboard web application

**Updated Configuration:**
- Makefile: Removed build/test/release targets for moved components
- CLAUDE.md: Simplified to focus on core blockchain components
- devbox.json: Removed scripts for moved services
- docker-compose.yml: Removed hway, postgres, redis, auth, dash services
- .github/scopes.yml: Removed CI scopes for migrated components
- .goreleaser.yml: Updated release configuration

**Added Migration Documentation:**
- MIGRATE_HWAY.md: Comprehensive Highway service architecture and migration guide
- MIGRATE_MOTR.md: Comprehensive Motor/Worker/Vault architecture and migration guide

These migration documents provide complete context for setting up the new repositories including architecture diagrams, component breakdowns, API documentation, and migration checklists.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* No commit suggestions generated

* chore: Remove contracts references and documentation

Removed all references to the contracts directory that was migrated to a separate repository.

**Changes:**
- .gitignore: Removed contract-specific ignore patterns for DAO and wSNR contracts
- .gitignore: Removed hway and motr binary references (already migrated)
- .rgignore: Removed contracts, chains, and crypto directory references
- docs/reference/contracts/: Removed DAO.mdx and wSNR.mdx documentation files

This completes the cleanup of migrated components from the repository.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* docs: add crypto library migration documentation

Added comprehensive migration documentation for the crypto library that was
moved to sonr-io/crypto repository. This documentation provides complete context
for understanding the cryptographic primitives and protocols used throughout
the Sonr ecosystem.

## Key Documentation Added

### MIGRATE_CRYPTO.md
Complete documentation of the crypto library covering:

**Core Cryptographic Primitives**
- Elliptic curve implementations (Ed25519, Secp256k1, P-256, BLS12-381, Pallas/Vesta)
- Native curve arithmetic with optimized field operations
- Pairing-friendly curves for BLS signatures

**Multi-Party Computation (MPC)**
- MPC enclave for vault key generation and management
- Threshold cryptography (TECDSA, TED25519 with FROST protocol)
- Distributed Key Generation (DKG) via Gennaro and FROST protocols
- Secret sharing schemes (Shamir, Feldman VSS, Pedersen VSS)

**Digital Signature Schemes**
- BLS signatures with aggregation support
- BBS+ signatures for selective disclosure
- Schnorr signatures (standard and Mina/NEM variants)
- ECDSA with deterministic nonce generation

**Zero-Knowledge Proofs**
- Bulletproofs for range proofs
- Inner Product Arguments (IPA)
- Batch verification support

**Advanced Cryptographic Protocols**
- Cryptographic accumulators for set membership proofs
- Paillier homomorphic encryption
- Oblivious Transfer (OT) protocols
- Verifiable Random Functions (VRF)

**Key Management & Identity**
- DID key management with multi-chain support
- Multi-algorithm public key handling
- Wallet address derivation (Bitcoin, Ethereum, Cosmos, Solana, etc.)

**UCAN Integration**
- User-Controlled Authorization Networks
- Capability delegation and attenuation
- JWT-based capability tokens
- MPC-enabled UCAN signing

**Security Utilities**
- AEAD encryption (AES-GCM, AES-SIV)
- Argon2 key derivation
- ECIES encryption
- Secure memory handling

### MIGRATE_MOTR.md Updates
Updated Motor migration documentation to clarify that the crypto library
is now a separate external dependency at github.com/sonr-io/crypto v1.0.1

## Repository Context

The crypto library has been successfully migrated to its own repository
and is published as a Go module. It serves as the foundational cryptographic
layer for:
- Sonr blockchain (snrd) - DID signatures, vault operations
- Highway service (hway) - UCAN token signing, WebAuthn
- Motor/Worker (motr) - MPC vault operations, threshold signatures

## Integration Impact

All Sonr ecosystem components now depend on the external crypto library:
```go
require github.com/sonr-io/crypto v1.0.1
```

The migration enables independent versioning and maintenance of cryptographic
primitives while maintaining security and compatibility across the ecosystem.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* No commit suggestions generated

* No commit suggestions generated

* No commit suggestions generated

---------

Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Prad Nukala
2025-10-10 11:47:18 -04:00
committed by GitHub
co-authored by Claude
parent 7570d67787
commit 40eadc995e
1306 changed files with 2854 additions and 316038 deletions
-18
View File
@@ -1,18 +0,0 @@
[tool.commitizen]
name = "cz_customize"
tag_format = "hway/v$version"
ignored_tag_formats = ["*/v${version}", "v${version}"]
version_scheme = "semver"
version_provider = "scm"
update_changelog_on_bump = true
changelog_file = "CHANGELOG.md"
major_version_zero = true
annotated_tag = true
pre_bump_hooks = ["bash scripts/hook-bump-pre.sh"]
post_bump_hooks = ["goreleaser release --clean -f cmd/hway/.goreleaser.yml"]
[tool.commitizen.customize]
bump_pattern = "^(feat|fix|refactor|perf|BREAKING CHANGE)"
bump_map = { "BREAKING CHANGE" = "MAJOR", "feat" = "MINOR", "fix" = "PATCH", "refactor" = "PATCH", "perf" = "PATCH" }
default_bump = "PATCH"
changelog_pattern = "^(feat|fix|refactor|docs|build)\\(hway\\)(!)?:"
-293
View File
@@ -1,293 +0,0 @@
# yaml-language-server: $schema=https://goreleaser.com/static/schema-pro.json
---
version: 2
dist: dist/hway
monorepo:
tag_prefix: hway/
dir: cmd/hway
project_name: hway
before:
hooks:
- go mod download
builds:
# Hway Darwin AMD64
- id: hway-darwin-amd64
main: .
binary: hway
mod_timestamp: "{{ .CommitTimestamp }}"
env:
- CGO_ENABLED=1
- CC=o64-clang
- CXX=o64-clang++
goos:
- darwin
goarch:
- amd64
flags:
- -mod=readonly
- -trimpath
ldflags:
- -X main.Version={{.Version}}
- -X main.Commit={{.Commit}}
- -s -w # Strip debug info
# Hway Darwin ARM64
- id: hway-darwin-arm64
main: .
binary: hway
mod_timestamp: "{{ .CommitTimestamp }}"
env:
- CGO_ENABLED=1
- CC=oa64-clang
- CXX=oa64-clang++
goos:
- darwin
goarch:
- arm64
flags:
- -mod=readonly
- -trimpath
ldflags:
- -X main.Version={{.Version}}
- -X main.Commit={{.Commit}}
- -s -w # Strip debug info
# Hway Linux AMD64
- id: hway-linux-amd64
main: .
binary: hway
mod_timestamp: "{{ .CommitTimestamp }}"
env:
- CGO_ENABLED=1
- CC=x86_64-linux-gnu-gcc
- CXX=x86_64-linux-gnu-g++
goos:
- linux
goarch:
- amd64
flags:
- -mod=readonly
- -trimpath
ldflags:
- -X main.Version={{.Version}}
- -X main.Commit={{.Commit}}
- -s -w
# Hway Linux ARM64
- id: hway-linux-arm64
main: .
binary: hway
mod_timestamp: "{{ .CommitTimestamp }}"
env:
- CGO_ENABLED=1
- CC=aarch64-linux-gnu-gcc
- CXX=aarch64-linux-gnu-g++
goos:
- linux
goarch:
- arm64
flags:
- -mod=readonly
- -trimpath
ldflags:
- -X main.Version={{.Version}}
- -X main.Commit={{.Commit}}
- -s -w
aur_sources:
- name: hway
disable: true
homepage: "https://sonr.io"
description: "Highway service - bridge between the Public Internet and Sonr blockchain"
maintainers:
- "Sonr <support@sonr.io>"
license: "GPL-3.0"
private_key: "{{ .Env.AUR_KEY }}"
git_url: "ssh://[email protected]/hway.git"
skip_upload: auto
provides:
- hway
conflicts:
- hway-bin
depends:
- glibc
- redis
optdepends:
- "docker: for container-based vault operations"
makedepends:
- go
- git
- make
commit_msg_template: "Update to {{ .Tag }}"
commit_author:
name: goreleaserbot
email: "prad@sonr.io"
prepare: |-
cd "${pkgname}_${pkgver}"
go mod download
build: |-
cd "${pkgname}_${pkgver}"
export CGO_ENABLED=1
export CGO_CPPFLAGS="${CPPFLAGS}"
export CGO_CFLAGS="${CFLAGS}"
export CGO_CXXFLAGS="${CXXFLAGS}"
export CGO_LDFLAGS="${LDFLAGS}"
export GOFLAGS="-buildmode=pie -trimpath -mod=readonly -modcacherw"
go build \
-ldflags="-w -s -buildid='' -linkmode=external \
-X main.Version=${pkgver}" \
-o hway ./cmd/hway
chmod +x ./hway
package: |-
cd "${pkgname}_${pkgver}"
# bin
install -Dm755 "./hway" "${pkgdir}/usr/bin/hway"
# license
if [ -f "./LICENSE" ]; then
install -Dm644 "./LICENSE" "${pkgdir}/usr/share/licenses/hway/LICENSE"
fi
# readme
if [ -f "./README.md" ]; then
install -Dm644 "./README.md" "${pkgdir}/usr/share/doc/hway/README.md"
fi
nix:
- name: hway
ids:
- hway
homepage: "https://sonr.io"
description: "Highway network component for Sonr"
license: "gpl3"
path: pkgs/hway/default.nix
commit_msg_template: "hway: {{ .Tag }}"
dependencies:
- stdenv
- glibc
extra_install: |-
wrapProgram $out/bin/hway --prefix PATH : ${lib.makeBinPath [ glibc stdenv.cc.cc.lib ]}
repository:
owner: sonr-io
name: nur
branch: main
token: "{{ .Env.GITHUB_TOKEN }}"
archives:
- id: hway
ids:
- hway-linux-amd64
- hway-linux-arm64
- hway-darwin-amd64
- hway-darwin-arm64
name_template: >-
hway_{{ .Os }}_{{- if eq .Arch "amd64" }}x86_64 {{- else if eq .Arch "386" }}i386 {{- else }}{{ .Arch }}{{ end }}
formats: ["tar.gz"]
files:
- src: README*
wrap_in_directory: false
homebrew_casks:
- name: hway
ids:
- hway
homepage: "https://sonr.io"
description: "Highway service - bridge between the Public Internet and Sonr blockchain"
commit_msg_template: "Brew cask update for {{ .ProjectName }} version {{ .Tag }}"
directory: Casks
repository:
owner: sonr-io
name: homebrew-tap
branch: main
token: "{{ .Env.GITHUB_TOKEN }}"
commit_author:
name: goreleaserbot
email: "prad@sonr.io"
hooks:
post:
install: |
if OS.mac?
system_command "/usr/bin/xattr", args: ["-dr", "com.apple.quarantine", "#{staged_path}/hway"]
end
nfpms:
- id: hway
package_name: hway
ids:
- hway-linux-amd64
- hway-linux-arm64
file_name_template: "hway_{{ .Os }}_{{ .Arch }}{{ .ConventionalExtension }}"
vendor: Sonr
homepage: "https://sonr.io"
maintainer: "Sonr <support@sonr.io>"
description: "Hway is the bridge between the Public Internet and the Sonr blockchain."
license: "GPL-3.0"
formats:
- rpm
- deb
- apk
- archlinux
contents:
- src: README*
dst: /usr/share/doc/hway
bindir: /usr/bin
section: net
priority: optional
blobs:
- provider: s3
endpoint: https://eb37925850388bca807b7fab964c12bb.r2.cloudflarestorage.com
bucket: releases
region: auto
directory: "hway/{{ .Tag }}"
ids:
- hway
release:
disable: false
github:
owner: sonr-io
name: sonr
name_template: "{{.ProjectName}}/{{ .Tag }}"
draft: false
replace_existing_draft: false # Don't replace drafts
replace_existing_artifacts: false # Append, don't replace
mode: append # Explicitly set to append mode
checksum:
name_template: 'hway_checksums.txt'
npms:
- name: "@sonr.io/hway"
ids:
- hway
description: "Highway service - bridge between the Public Internet and Sonr blockchain"
homepage: "https://sonr.io"
license: "GPL-3.0"
author: "Sonr <support@sonr.io>"
repository: "https://github.com/sonr-io/sonr"
bugs: "https://github.com/sonr-io/sonr/issues"
keywords:
- highway
- bridge
- blockchain
- sonr
- service
access: public
format: tar.gz
snapshot:
version_template: "{{ incpatch .Version }}-dev"
# Changelog configuration
changelog:
sort: asc
filters:
exclude:
- '^docs:'
- '^test:'
- '^chore:'
-5
View File
@@ -1,5 +0,0 @@
## hway/v0.0.3 (2025-10-04)
## hway/v0.0.2 (2025-10-04)
## hway/v0.0.1 (2025-10-03)
-77
View File
@@ -1,77 +0,0 @@
# Use build argument for base image to allow using pre-cached base
ARG BASE_IMAGE=golang:1.24.7-alpine3.22
# --------------------------------------------------------
# Highway service build stage
FROM ${BASE_IMAGE} AS builder
SHELL ["/bin/sh", "-ecuxo", "pipefail"]
# Install build dependencies
RUN apk add --no-cache \
ca-certificates \
build-base \
git \
linux-headers \
bash
WORKDIR /code
# Copy entire source code
COPY . .
# Fix git ownership issue
RUN git config --global --add safe.directory /code
# Download Go modules
RUN --mount=type=cache,target=/go/pkg/mod \
--mount=type=cache,target=/root/.cache/go-build \
go mod download
# Build Highway binary
RUN --mount=type=cache,target=/go/pkg/mod \
--mount=type=cache,target=/root/.cache/go-build \
set -eux; \
VERSION=$(git describe --tags --always 2>/dev/null || echo "dev"); \
COMMIT=$(git log -1 --format='%H' 2>/dev/null || echo "unknown"); \
CGO_ENABLED=1 GOOS=linux \
go build \
-mod=readonly \
-ldflags "-X main.Version=${VERSION} \
-X main.Commit=${COMMIT} \
-w -s" \
-buildvcs=false \
-trimpath \
-o /code/build/hway \
./cmd/hway
# --------------------------------------------------------
# Highway runtime image
FROM alpine:3.17
LABEL org.opencontainers.image.title="Sonr Highway Service"
LABEL org.opencontainers.image.source="https://github.com/sonr-io/sonr"
# Copy binary from builder
COPY --from=builder /code/build/hway /usr/bin/hway
# Install runtime dependencies
RUN apk add --no-cache ca-certificates wget
# Create non-root user
RUN adduser -D -u 1000 highway
# Set working directory
WORKDIR /home/highway
# Switch to non-root user
USER highway
# Health check endpoint
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD wget --spider -q http://localhost:8090/health || exit 1
# Expose Highway port
EXPOSE 8090
# Set default command
ENTRYPOINT ["/usr/bin/hway"]
-110
View File
@@ -1,110 +0,0 @@
#!/usr/bin/make -f
# Version and build information
GIT_ROOT := $(shell git rev-parse --show-toplevel)
VERSION := $(shell echo $(shell git describe --tags 2>/dev/null || echo "dev") | sed 's/^v//')
COMMIT := $(shell git log -1 --format='%H')
BUMP_LEVEL := PATCH
# Build configuration
BUILD_FLAGS := -trimpath
# Linker flags for version info
ldflags = -X main.Version=$(VERSION) \
-X main.Commit=$(COMMIT) \
-s -w
BUILD_FLAGS += -ldflags '$(ldflags)'
HWAY_OUT := $(GIT_ROOT)/build/hway
.PHONY: all build install clean test version help docker
all: build
build:
ifeq ($(OS),Windows_NT)
$(error hway server not supported on Windows)
else
@echo "Building Highway service..."
@go build -mod=readonly $(BUILD_FLAGS) -o $(HWAY_OUT) .
@echo "Binary built: ../../build/hway"
endif
install:
ifeq ($(OS),Windows_NT)
$(error hway server not supported on Windows)
else
@echo "Installing Highway service..."
@go install -mod=readonly $(BUILD_FLAGS) .
@echo "Binary installed to $(GOPATH)/bin/hway"
endif
tidy:
@echo "Tidying Go module..."
@go mod tidy
clean:
@echo "Cleaning build artifacts..."
@rm -f $(HWAY_OUT)
@echo "Clean complete"
test:
@echo "Running Highway service tests..."
@go test -v -race ./...
release:
@echo "Creating hway release..."
@cd $(GIT_ROOT) && cz --config cmd/hway/.cz.toml --no-raise 6,21 bump --yes --increment PATCH
snapshot:
@echo "Dry-Run Bumping Highway version..."
@cd $(GIT_ROOT) && cz --config cmd/hway/.cz.toml bump --yes --no-verify --dry-run --increment PATCH
@echo "Creating hway snapshots for all platforms..."
@cd $(GIT_ROOT) && goreleaser release --snapshot --clean -f cmd/hway/.goreleaser.yml
# Docker build targets
docker:
@echo "Building Highway Docker image..."
@docker build -f Dockerfile -t onsonr/hway:latest -t ghcr.io/sonr-io/hway:latest ../..
@echo "Docker image built and tagged:"
@echo " - onsonr/hway:latest"
@echo " - ghcr.io/sonr-io/hway:latest"
docker-local:
@echo "Building Highway Docker image with local context..."
@docker build -f Dockerfile -t onsonr/hway:local -t ghcr.io/sonr-io/hway:local ../..
@echo "Docker image built and tagged:"
@echo " - onsonr/hway:local"
@echo " - ghcr.io/sonr-io/hway:local"
version:
@echo "Highway Service"
@echo "==============="
@echo "Version: $(VERSION)"
@echo "Commit: $(COMMIT)"
help:
@echo "Highway Service Makefile"
@echo "========================"
@echo ""
@echo "Highway is an Asynq-based task processing service for vault operations,"
@echo "using Redis-backed job queues and Proto.Actor framework for concurrency."
@echo ""
@echo "Available targets:"
@echo " build - Build Highway binary (default)"
@echo " install - Install Highway to GOPATH/bin"
@echo " docker - Build Docker image (onsonr/hway:latest)"
@echo " clean - Remove build artifacts"
@echo " test - Run Highway tests"
@echo " version - Display version information"
@echo " help - Show this help message"
@echo ""
@echo "Requirements:"
@echo " - Redis server running on 127.0.0.1:6379"
@echo " - IPFS nodes for vault operations"
@echo ""
@echo "Examples:"
@echo " make build # Build the Highway service"
@echo " make test # Run tests"
@echo " make install # Install to GOPATH/bin"
Binary file not shown.
-312
View File
@@ -1,312 +0,0 @@
module hway
go 1.24.7
// overrides
replace (
cosmossdk.io/core => cosmossdk.io/core v0.11.0
cosmossdk.io/store => github.com/evmos/cosmos-sdk/store v0.0.0-20240718141609-414cbd051fbe
github.com/CosmWasm/wasmd => github.com/rollchains/wasmd v0.50.0-evm
github.com/cosmos/cosmos-sdk => github.com/strangelove-ventures/cosmos-sdk v0.0.0-20250317212103-0767f8c5b1e5
github.com/cosmos/evm => github.com/strangelove-ventures/cosmos-evm v0.2.0
github.com/ethereum/go-ethereum => github.com/evmos/go-ethereum v1.10.26-evmos-rc2
github.com/sonr-io/sonr => ../../
github.com/sonr-io/sonr/crypto => ../../crypto
github.com/spf13/viper => github.com/spf13/viper v1.17.0 // v1.18+ breaks app overrides
nhooyr.io/websocket => nhooyr.io/websocket v1.8.17
)
replace (
github.com/99designs/keyring => github.com/cosmos/keyring v1.2.0
// Fix btcec version for evmos compatibility
github.com/btcsuite/btcd/btcec/v2 => github.com/btcsuite/btcd/btcec/v2 v2.3.2
// dgrijalva/jwt-go is deprecated and doesn't receive security updates.
// See: https://github.com/cosmos/cosmos-sdk/issues/13134
github.com/dgrijalva/jwt-go => github.com/golang-jwt/jwt/v4 v4.4.2
// Fix upstream GHSA-h395-qcrw-5vmq vulnerability.
// See: https://github.com/cosmos/cosmos-sdk/issues/10409
github.com/gin-gonic/gin => github.com/gin-gonic/gin v1.8.1
// pin version! 126854af5e6d has issues with the store so that queries fail
github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7
)
require github.com/sonr-io/sonr v0.0.0-00010101000000-000000000000
require (
cosmossdk.io/api v0.7.6 // indirect
cosmossdk.io/collections v0.4.0 // indirect
cosmossdk.io/core v0.12.0 // indirect
cosmossdk.io/depinject v1.1.0 // indirect
cosmossdk.io/errors v1.0.1 // indirect
cosmossdk.io/math v1.5.0 // indirect
cosmossdk.io/orm v1.0.0-beta.3 // indirect
cosmossdk.io/store v1.1.1 // indirect
cosmossdk.io/x/tx v0.13.7 // indirect
github.com/Oudwins/zog v0.21.6 // indirect
github.com/asynkron/protoactor-go v0.0.0-20240822202345-3c0e61ca19c9 // indirect
github.com/biter777/countries v1.7.5 // indirect
github.com/cosmos/cosmos-proto v1.0.0-beta.5 // indirect
github.com/cosmos/gogoproto v1.7.0 // indirect
github.com/extism/go-sdk v1.7.1 // indirect
github.com/fxamacker/cbor/v2 v2.9.0 // indirect
github.com/golang-jwt/jwt/v5 v5.3.0 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/go-tpm v0.9.5 // indirect
github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect
github.com/ipfs/boxo v0.32.0 // indirect
github.com/ipfs/kubo v0.35.0 // indirect
github.com/labstack/echo/v4 v4.13.4 // indirect
github.com/labstack/gommon v0.4.2 // indirect
github.com/sonr-io/sonr/crypto v0.0.0-00010101000000-000000000000 // indirect
github.com/stretchr/testify v1.10.0 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasttemplate v1.2.2 // indirect
github.com/x448/float16 v0.8.4 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20250106144421-5f5ef82da422 // indirect
google.golang.org/grpc v1.71.0 // indirect
google.golang.org/protobuf v1.36.6 // indirect
)
require (
cosmossdk.io/log v1.5.0 // indirect
filippo.io/edwards25519 v1.1.0 // indirect
github.com/DataDog/zstd v1.5.6-0.20230824185856-869dae002e5e // indirect
github.com/Workiva/go-datastructures v1.1.3 // indirect
github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b // indirect
github.com/benbjohnson/clock v1.3.5 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/bits-and-blooms/bitset v1.24.0 // indirect
github.com/blang/semver/v4 v4.0.0 // indirect
github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect
github.com/bwesterb/go-ristretto v1.2.3 // indirect
github.com/bytedance/sonic v1.14.0 // indirect
github.com/bytedance/sonic/loader v0.3.0 // indirect
github.com/caddyserver/certmagic v0.21.6 // indirect
github.com/caddyserver/zerossl v0.1.3 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/cloudwego/base64x v0.1.5 // indirect
github.com/cockroachdb/apd/v3 v3.2.1 // indirect
github.com/cockroachdb/crlib v0.0.0-20241015224233-894974b3ad94 // indirect
github.com/cockroachdb/errors v1.11.3 // indirect
github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce // indirect
github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect
github.com/cockroachdb/pebble v1.1.2 // indirect
github.com/cockroachdb/pebble/v2 v2.0.3 // indirect
github.com/cockroachdb/redact v1.1.5 // indirect
github.com/cockroachdb/swiss v0.0.0-20250624142022-d6e517c1d961 // indirect
github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect
github.com/cometbft/cometbft v0.38.17 // indirect
github.com/cometbft/cometbft-db v0.14.1 // indirect
github.com/consensys/gnark-crypto v0.19.0 // indirect
github.com/cosmos/btcutil v1.0.5 // indirect
github.com/cosmos/cosmos-db v1.1.1 // indirect
github.com/cosmos/cosmos-sdk v0.53.4 // indirect
github.com/cosmos/ics23/go v0.11.0 // indirect
github.com/crackcomm/go-gitignore v0.0.0-20241020182519-7843d2ba8fdf // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 // indirect
github.com/dgraph-io/badger/v4 v4.2.0 // indirect
github.com/dgraph-io/ristretto v0.1.1 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/dustinxie/ecc v0.0.0-20210511000915-959544187564 // indirect
github.com/dylibso/observe-sdk/go v0.0.0-20240819160327-2d926c5d788a // indirect
github.com/emirpasic/gods v1.18.1 // indirect
github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5 // indirect
github.com/flynn/noise v1.1.0 // indirect
github.com/francoispqt/gojay v1.2.13 // indirect
github.com/gammazero/deque v1.0.0 // indirect
github.com/getsentry/sentry-go v0.27.0 // indirect
github.com/go-kit/kit v0.13.0 // indirect
github.com/go-kit/log v0.2.1 // indirect
github.com/go-logfmt/logfmt v0.6.0 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/gobwas/glob v0.2.3 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/glog v1.2.4 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/snappy v0.0.5-0.20231225225746-43d5d4cd4e0e // indirect
github.com/google/btree v1.1.3 // indirect
github.com/google/flatbuffers v23.5.26+incompatible // indirect
github.com/google/go-cmp v0.7.0 // indirect
github.com/google/gopacket v1.1.19 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/gopherjs/gopherjs v1.17.2 // indirect
github.com/gorilla/websocket v1.5.3 // indirect
github.com/gtank/merlin v0.1.1 // indirect
github.com/hashicorp/go-immutable-radix v1.3.1 // indirect
github.com/hashicorp/go-metrics v0.5.3 // indirect
github.com/hashicorp/go-uuid v1.0.3 // indirect
github.com/hashicorp/golang-lru v1.0.2 // indirect
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
github.com/hdevalence/ed25519consensus v0.1.0 // indirect
github.com/hibiken/asynq v0.25.1 // indirect
github.com/huin/goupnp v1.3.0 // indirect
github.com/iancoleman/strcase v0.3.0 // indirect
github.com/ianlancetaylor/demangle v0.0.0-20240805132620-81f5be970eca // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/ipfs/bbloom v0.0.4 // indirect
github.com/ipfs/go-bitfield v1.1.0 // indirect
github.com/ipfs/go-block-format v0.2.1 // indirect
github.com/ipfs/go-cid v0.5.0 // indirect
github.com/ipfs/go-datastore v0.8.2 // indirect
github.com/ipfs/go-ds-measure v0.2.2 // indirect
github.com/ipfs/go-fs-lock v0.1.1 // indirect
github.com/ipfs/go-ipfs-cmds v0.14.1 // indirect
github.com/ipfs/go-ipld-cbor v0.2.0 // indirect
github.com/ipfs/go-ipld-format v0.6.1 // indirect
github.com/ipfs/go-ipld-legacy v0.2.1 // indirect
github.com/ipfs/go-log v1.0.5 // indirect
github.com/ipfs/go-log/v2 v2.6.0 // indirect
github.com/ipfs/go-metrics-interface v0.3.0 // indirect
github.com/ipfs/go-unixfsnode v1.10.1 // indirect
github.com/ipld/go-car/v2 v2.14.3 // indirect
github.com/ipld/go-codec-dagpb v1.7.0 // indirect
github.com/ipld/go-ipld-prime v0.21.0 // indirect
github.com/ipshipyard/p2p-forge v0.5.1 // indirect
github.com/jackpal/go-nat-pmp v1.0.2 // indirect
github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect
github.com/jmhodges/levigo v1.0.0 // indirect
github.com/klauspost/compress v1.18.0 // indirect
github.com/klauspost/cpuid/v2 v2.2.10 // indirect
github.com/koron/go-ssdp v0.0.6 // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/labstack/echo-jwt/v4 v4.3.1 // indirect
github.com/libdns/libdns v0.2.2 // indirect
github.com/libp2p/go-buffer-pool v0.1.0 // indirect
github.com/libp2p/go-cidranger v1.1.0 // indirect
github.com/libp2p/go-flow-metrics v0.2.0 // indirect
github.com/libp2p/go-libp2p v0.43.0 // indirect
github.com/libp2p/go-libp2p-asn-util v0.4.1 // indirect
github.com/libp2p/go-libp2p-kad-dht v0.33.1 // indirect
github.com/libp2p/go-libp2p-kbucket v0.7.0 // indirect
github.com/libp2p/go-libp2p-record v0.3.1 // indirect
github.com/libp2p/go-libp2p-routing-helpers v0.7.5 // indirect
github.com/libp2p/go-msgio v0.3.0 // indirect
github.com/libp2p/go-netroute v0.2.2 // indirect
github.com/libp2p/go-reuseport v0.4.0 // indirect
github.com/linxGnu/grocksdb v1.9.8 // indirect
github.com/lithammer/shortuuid/v4 v4.0.0 // indirect
github.com/lmittmann/tint v1.0.3 // indirect
github.com/mattn/go-colorable v0.1.14 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mholt/acmez/v3 v3.0.0 // indirect
github.com/miekg/dns v1.1.66 // indirect
github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643 // indirect
github.com/minio/sha256-simd v1.0.1 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/mr-tron/base58 v1.2.0 // indirect
github.com/multiformats/go-base32 v0.1.0 // indirect
github.com/multiformats/go-base36 v0.2.0 // indirect
github.com/multiformats/go-multiaddr v0.16.0 // indirect
github.com/multiformats/go-multiaddr-dns v0.4.1 // indirect
github.com/multiformats/go-multiaddr-fmt v0.1.0 // indirect
github.com/multiformats/go-multibase v0.2.0 // indirect
github.com/multiformats/go-multicodec v0.9.1 // indirect
github.com/multiformats/go-multihash v0.2.3 // indirect
github.com/multiformats/go-multistream v0.6.1 // indirect
github.com/multiformats/go-varint v0.1.0 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a // indirect
github.com/onsi/gomega v1.36.2 // indirect
github.com/opentracing/opentracing-go v1.2.0 // indirect
github.com/orcaman/concurrent-map v1.0.0 // indirect
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect
github.com/petar/GoLLRB v0.0.0-20210522233825-ae3b015fd3e9 // indirect
github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect
github.com/pion/datachannel v1.5.10 // indirect
github.com/pion/dtls/v2 v2.2.12 // indirect
github.com/pion/dtls/v3 v3.0.6 // indirect
github.com/pion/ice/v4 v4.0.10 // indirect
github.com/pion/interceptor v0.1.40 // indirect
github.com/pion/logging v0.2.3 // indirect
github.com/pion/mdns/v2 v2.0.7 // indirect
github.com/pion/randutil v0.1.0 // indirect
github.com/pion/rtcp v1.2.15 // indirect
github.com/pion/rtp v1.8.19 // indirect
github.com/pion/sctp v1.8.39 // indirect
github.com/pion/sdp/v3 v3.0.13 // indirect
github.com/pion/srtp/v3 v3.0.6 // indirect
github.com/pion/stun v0.6.1 // indirect
github.com/pion/stun/v3 v3.0.0 // indirect
github.com/pion/transport/v2 v2.2.10 // indirect
github.com/pion/transport/v3 v3.0.7 // indirect
github.com/pion/turn/v4 v4.0.2 // indirect
github.com/pion/webrtc/v4 v4.1.2 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/polydawn/refmt v0.89.0 // indirect
github.com/prometheus/client_golang v1.22.0 // indirect
github.com/prometheus/client_model v0.6.2 // indirect
github.com/prometheus/common v0.64.0 // indirect
github.com/prometheus/procfs v0.16.1 // indirect
github.com/quic-go/qpack v0.5.1 // indirect
github.com/quic-go/quic-go v0.54.0 // indirect
github.com/quic-go/webtransport-go v0.9.0 // indirect
github.com/redis/go-redis/v9 v9.11.0 // indirect
github.com/robfig/cron/v3 v3.0.1 // indirect
github.com/rogpeppe/go-internal v1.14.1 // indirect
github.com/rs/cors v1.11.1 // indirect
github.com/rs/zerolog v1.33.0 // indirect
github.com/samber/lo v1.47.0 // indirect
github.com/sasha-s/go-deadlock v0.3.5 // indirect
github.com/smarty/assertions v1.15.0 // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect
github.com/spf13/cast v1.9.2 // indirect
github.com/spf13/cobra v1.8.1 // indirect
github.com/spf13/pflag v1.0.6 // indirect
github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect
github.com/tendermint/go-amino v0.16.0 // indirect
github.com/tetratelabs/wabin v0.0.0-20230304001439-f6f874872834 // indirect
github.com/tetratelabs/wazero v1.9.0 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/twmb/murmur3 v1.1.8 // indirect
github.com/whyrusleeping/base32 v0.0.0-20170828182744-c30ac30633cc // indirect
github.com/whyrusleeping/cbor v0.0.0-20171005072247-63513f603b11 // indirect
github.com/whyrusleeping/cbor-gen v0.1.2 // indirect
github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f // indirect
github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 // indirect
github.com/wlynxg/anet v0.0.5 // indirect
github.com/zeebo/assert v1.3.0 // indirect
github.com/zeebo/blake3 v0.2.4 // indirect
go.etcd.io/bbolt v1.4.0-alpha.0.0.20240404170359-43604f3112c5 // indirect
go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
go.opentelemetry.io/otel v1.35.0 // indirect
go.opentelemetry.io/otel/exporters/prometheus v0.44.0 // indirect
go.opentelemetry.io/otel/metric v1.35.0 // indirect
go.opentelemetry.io/otel/sdk v1.34.0 // indirect
go.opentelemetry.io/otel/sdk/metric v1.34.0 // indirect
go.opentelemetry.io/otel/trace v1.35.0 // indirect
go.opentelemetry.io/proto/otlp v1.3.1 // indirect
go.uber.org/dig v1.19.0 // indirect
go.uber.org/fx v1.24.0 // indirect
go.uber.org/mock v0.5.2 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.27.0 // indirect
go.uber.org/zap/exp v0.3.0 // indirect
go.yaml.in/yaml/v2 v2.4.2 // indirect
go4.org v0.0.0-20230225012048-214862532bf5 // indirect
golang.org/x/arch v0.3.0 // indirect
golang.org/x/crypto v0.42.0 // indirect
golang.org/x/exp v0.0.0-20250606033433-dcc06ee1d476 // indirect
golang.org/x/mod v0.27.0 // indirect
golang.org/x/net v0.43.0 // indirect
golang.org/x/sync v0.17.0 // indirect
golang.org/x/sys v0.36.0 // indirect
golang.org/x/text v0.29.0 // indirect
golang.org/x/time v0.12.0 // indirect
golang.org/x/tools v0.36.0 // indirect
golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect
gonum.org/v1/gonum v0.16.0 // indirect
google.golang.org/genproto v0.0.0-20240701130421-f6361c86f094 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
lukechampine.com/blake3 v1.4.1 // indirect
sigs.k8s.io/yaml v1.5.0 // indirect
)
-1382
View File
File diff suppressed because it is too large Load Diff
-20
View File
@@ -1,20 +0,0 @@
// Package main provides the Highway service, a UCAN-based task processing service
// that acts as a bridge proxy for MPC operations and decentralized identity management.
//
// The service processes asynchronous UCAN (User-Controlled Authorization Networks) tasks
// including token creation, delegation, signing, verification, and DID generation.
// It serves as a proxy between the bridge handlers and the underlying blockchain operations.
package main
import (
"github.com/sonr-io/sonr/bridge"
)
func main() {
// Create and configure the Highway service
service := bridge.NewHighwayService()
defer service.Shutdown()
// Start the service and block until shutdown
service.Start()
}
-4
View File
@@ -1,4 +0,0 @@
package main
// Version is set by commitizen during release process
var Version = "dev"
-18
View File
@@ -1,18 +0,0 @@
[tool.commitizen]
name = "cz_customize"
tag_format = "motr/v$version"
ignored_tag_formats = ["*/v${version}", "v${version}"]
version_scheme = "semver"
version_provider = "scm"
update_changelog_on_bump = true
changelog_file = "CHANGELOG.md"
major_version_zero = true
annotated_tag = true
pre_bump_hooks = ["bash scripts/hook-bump-pre.sh"]
post_bump_hooks = ["goreleaser release --clean -f cmd/motr/.goreleaser.yml"]
[tool.commitizen.customize]
bump_pattern = "^(feat|fix|refactor|perf|BREAKING CHANGE)"
bump_map = { "BREAKING CHANGE" = "MAJOR", "feat" = "MINOR", "fix" = "PATCH", "refactor" = "PATCH", "perf" = "PATCH" }
default_bump = "PATCH"
changelog_pattern = "^(feat|fix|refactor|docs|build)\\(motr\\)(!)?:"
-75
View File
@@ -1,75 +0,0 @@
# yaml-language-server: $schema=https://goreleaser.com/static/schema-pro.json
---
version: 2
dist: dist/motr
monorepo:
tag_prefix: motr/
dir: cmd/motr
project_name: motr
before:
hooks:
- go mod download
builds:
- id: motr-wasm
main: .
binary: motr
no_unique_dist_dir: true
mod_timestamp: "{{ .CommitTimestamp }}"
env:
- CGO_ENABLED=0
goos:
- js
goarch:
- wasm
flags:
- -mod=readonly
- -trimpath
ldflags:
- -s -w
- -X main.version={{.Version}}
- -X main.commit={{.Commit}}
- -X main.date={{.Date}}
hooks:
post:
- cp dist/motr/motr.wasm packages/es/src/worker/app.wasm
archives:
- id: motr-wasm-archive
name_template: "motr_wasm_{{ .Version }}"
formats: ["binary"]
wrap_in_directory: true
blobs:
- provider: s3
endpoint: https://eb37925850388bca807b7fab964c12bb.r2.cloudflarestorage.com
bucket: releases
region: auto
directory: "motr/{{ .Tag }}"
release:
disable: false
github:
owner: sonr-io
name: sonr
name_template: "{{.ProjectName}}/{{ .Tag }}"
draft: false
replace_existing_draft: false # Don't replace drafts
replace_existing_artifacts: false # Append, don't replace
mode: append # Explicitly set to append mode
checksum:
name_template: "motr_checksums.txt"
snapshot:
version_template: "{{ incpatch .Version }}-dev"
# Changelog configuration
changelog:
sort: asc
filters:
exclude:
- "^docs:"
- "^test:"
- "^chore:"
-5
View File
@@ -1,5 +0,0 @@
## motr/v0.0.3 (2025-10-04)
## motr/v0.0.2 (2025-10-04)
## motr/v0.0.1 (2025-10-03)
-154
View File
@@ -1,154 +0,0 @@
#!/usr/bin/make -f
# Output configuration - outputs to ES package for bundling
GIT_ROOT := $(shell git rev-parse --show-toplevel)
ES_PACKAGE_DIR := $(GIT_ROOT)/packages/es/src/worker
WASM_FILE := app.wasm
JS_FILE := wasm_exec.js
OUTPUT_PATH := $(ES_PACKAGE_DIR)/$(WASM_FILE)
JS_PATH := $(ES_PACKAGE_DIR)/$(JS_FILE)
# Build configuration for WASM
GOOS := js
GOARCH := wasm
CGO_ENABLED := 0
# Version information
VERSION := $(shell echo $(shell git describe --tags 2>/dev/null || echo "dev") | sed 's/^v//')
COMMIT := $(shell git log -1 --format='%H')
# Go installation paths
GOROOT := $(shell go env GOROOT)
WASM_EXEC_SOURCE := $(GOROOT)/misc/wasm/wasm_exec.js
# Build flags
LDFLAGS := -s -w
BUILD_FLAGS := -ldflags="$(LDFLAGS)" -trimpath
.PHONY: all build clean test verify help version runtime tidy
all: build
build: clean-output runtime
@echo "Building Motor WASM module for ES package..."
@echo "Target: $(OUTPUT_PATH)"
@mkdir -p $(ES_PACKAGE_DIR)
@GOOS=$(GOOS) GOARCH=$(GOARCH) CGO_ENABLED=$(CGO_ENABLED) go build $(BUILD_FLAGS) -o $(OUTPUT_PATH) .
@echo "✅ Motor WASM module built successfully"
@echo "Output: $(OUTPUT_PATH)"
@ls -lh $(OUTPUT_PATH) | awk '{print "Size: " $$5}'
@$(MAKE) runtime
runtime:
@echo "Copying WASM runtime..."
@if [ -f "$(WASM_EXEC_SOURCE)" ]; then \
cp "$(WASM_EXEC_SOURCE)" "$(JS_PATH)"; \
echo "✅ WASM runtime copied to $(JS_PATH)"; \
else \
echo "⚠️ WASM runtime not found at $(WASM_EXEC_SOURCE)"; \
echo "You may need to manually copy wasm_exec.js"; \
fi
clean-output:
@echo "Cleaning previous builds..."
@rm -f $(OUTPUT_PATH)
@rm -f $(JS_PATH)
@mkdir -p $(ES_PACKAGE_DIR)
clean:
@echo "Cleaning build artifacts..."
@rm -f $(OUTPUT_PATH)
@rm -f $(JS_PATH)
@echo "✅ Clean complete"
release:
@echo "Creating motr release..."
@cd $(GIT_ROOT) && cz --config cmd/motr/.cz.toml --no-raise 6,21 bump --yes --increment PATCH
snapshot:
@echo "Dry-Run Bumping Motor version..."
@cd $(GIT_ROOT) && cz --config cmd/motr/.cz.toml bump --yes --no-verify --dry-run --increment PATCH
@echo "Creating motr snapshots for all platforms..."
@cd $(GIT_ROOT) && goreleaser release --snapshot --clean -f cmd/motr/.goreleaser.yml
tidy:
@echo "Tidying Motor module..."
@go mod tidy
@echo "✅ Tidy complete"
test:
@echo "Running Motor tests..."
@go test -v ./...
verify: build
@echo "Verifying WASM module..."
@if [ -f "$(OUTPUT_PATH)" ]; then \
file "$(OUTPUT_PATH)"; \
echo "✅ WASM file exists"; \
else \
echo "❌ WASM file not found"; \
exit 1; \
fi
@if [ -f "$(JS_PATH)" ]; then \
echo "✅ Runtime file exists"; \
else \
echo "⚠️ Runtime file not found"; \
fi
@if command -v wasm-validate >/dev/null 2>&1; then \
if wasm-validate "$(OUTPUT_PATH)"; then \
echo "✅ WASM module is valid"; \
else \
echo "❌ WASM module validation failed"; \
exit 1; \
fi \
else \
echo "⚠️ wasm-validate not available, skipping validation"; \
fi
@echo "✅ Verification complete"
@echo ""
@echo "The WASM module has been built in the ES package at:"
@echo " $(OUTPUT_PATH)"
@echo ""
@echo "The ES package will bundle and distribute this via jsDelivr"
version:
@echo "Motor WASM Service Worker"
@echo "========================="
@echo "Version: $(VERSION)"
@echo "Commit: $(COMMIT)"
@echo "Target OS: $(GOOS)"
@echo "Target Arch: $(GOARCH)"
@echo "Output: $(OUTPUT_PATH)"
help:
@echo "Motor WASM Module Makefile"
@echo "=========================="
@echo ""
@echo "Motor provides WebAssembly-based DWN and Wallet operations"
@echo "for the @sonr.io/es package to distribute via jsDelivr."
@echo ""
@echo "Available targets:"
@echo " build - Build Motor WASM module (default)"
@echo " clean - Remove all build artifacts"
@echo " test - Run Motor tests"
@echo " tidy - Tidy Go module dependencies"
@echo " verify - Build and validate WASM module"
@echo " version - Display version information"
@echo " help - Show this help message"
@echo ""
@echo "Build components (called by build):"
@echo " runtime - Copy WASM runtime (wasm_exec.js)"
@echo ""
@echo "Output location:"
@echo " ES Package: $(ES_PACKAGE_DIR)/"
@echo " WASM File: $(OUTPUT_PATH)"
@echo ""
@echo "Integration:"
@echo " The WASM module is built directly into the ES package plugins"
@echo " directory for bundling and CDN distribution. The TypeScript"
@echo " client in @sonr.io/es/plugins/motor handles service worker management."
@echo ""
@echo "Examples:"
@echo " make build # Build WASM module into ES package"
@echo " make verify # Build and validate the module"
@echo " make clean # Remove artifacts"
-385
View File
@@ -1,385 +0,0 @@
# Motor WASM Service Worker - Payment Gateway & OIDC Authorization
Motor is a WebAssembly-based HTTP server that runs as a Service Worker in the browser, providing secure payment processing and OpenID Connect (OIDC) authorization without requiring backend infrastructure.
## Overview
Motor implements a comprehensive payment gateway and identity provider that runs entirely in the browser:
1. **Payment Gateway**: W3C Payment Handler API compliant payment processing with PCI DSS compliance
2. **OIDC Authorization**: Complete OpenID Connect provider with JWT token management
3. **Service Worker**: Runs as a browser service worker using go-wasm-http-server
## Features
### Payment Gateway (W3C Payment Handler API)
- ✅ Process payment transactions securely
- ✅ PCI DSS compliant card tokenization
- ✅ Card validation (Luhn algorithm, CVV, expiry)
- ✅ Transaction signing with HMAC-SHA256
- ✅ AES-256-GCM encryption for sensitive data
- ✅ Payment method validation
- ✅ Refund processing
- ✅ Comprehensive audit logging
### OIDC Authorization
- ✅ Discovery endpoint (`.well-known/openid-configuration`)
- ✅ Authorization endpoint with PKCE support
- ✅ Token endpoint with JWT generation
- ✅ UserInfo endpoint
- ✅ JWKS endpoint for key rotation
- ✅ RS256 JWT signing
- ✅ Refresh token support
### Security Features
- ✅ Rate limiting (100 requests/minute per client)
- ✅ Origin validation
- ✅ Security headers (CSP, X-Frame-Options, etc.)
- ✅ CORS configuration
- ✅ Secure token generation
- ✅ Card number masking
- ✅ Sensitive data sanitization
## API Endpoints
### Payment Gateway Endpoints
#### Process Payment
```http
POST /api/payment/process
Content-Type: application/json
{
"method": "card",
"amount": 100.00,
"currency": "USD",
"card_number": "4111111111111111",
"cvv": "123",
"expiry_month": 12,
"expiry_year": 2025,
"billing_address": {
"line1": "123 Main St",
"city": "San Francisco",
"state": "CA",
"postal_code": "94105",
"country": "US"
}
}
```
#### Validate Payment Method
```http
POST /api/payment/validate
Content-Type: application/json
{
"method": "card",
"card_number": "4111111111111111",
"cvv": "123",
"expiry_month": 12,
"expiry_year": 2025
}
```
#### Get Payment Status
```http
GET /api/payment/status/:id
```
#### Process Refund
```http
POST /api/payment/refund
Content-Type: application/json
{
"payment_id": "pay_abc123",
"amount": 50.00,
"reason": "Customer request"
}
```
#### W3C Payment Handler API
```http
GET /payment/instruments
POST /payment/canmakepayment
POST /payment/paymentrequest
```
### OIDC Endpoints
#### Discovery
```http
GET /.well-known/openid-configuration
```
#### Authorization
```http
GET /authorize?client_id=CLIENT_ID&redirect_uri=URI&response_type=code&scope=openid%20profile
```
#### Token Exchange
```http
POST /token
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code&code=AUTH_CODE&client_id=CLIENT_ID
```
#### UserInfo
```http
GET /userinfo
Authorization: Bearer ACCESS_TOKEN
```
#### JWKS
```http
GET /.well-known/jwks.json
```
### Health & Monitoring
```http
GET /health
GET /status
```
## Building
### Using Make
```bash
# Build Motor WASM module
make motr-wasm
# Or build directly
cd cmd/motr
GOOS=js GOARCH=wasm go build -o ../../packages/es/src/plugins/motor/motor.wasm .
```
### Build Output
The WASM module is built to: `packages/es/src/plugins/motor/motor.wasm`
## Integration
### Service Worker Registration
```javascript
// motor-worker.js
importScripts('https://cdn.jsdelivr.net/gh/golang/go@go1.23.4/misc/wasm/wasm_exec.js');
importScripts('https://cdn.jsdelivr.net/gh/nlepage/go-wasm-http-server@v2.2.1/sw.js');
// Register Motor WASM as HTTP listener
registerWasmHTTPListener('motor.wasm', {
base: '/api'
});
```
### TypeScript Client Usage
```typescript
import { PaymentGatewayClient, OIDCClient } from '@sonr.io/es/plugins/motor';
// Initialize clients
const payment = new PaymentGatewayClient('https://localhost:3000');
const oidc = new OIDCClient('https://localhost:3000');
// Process a payment
const result = await payment.processPayment({
method: 'card',
amount: 100.00,
currency: 'USD',
card_number: '4111111111111111',
cvv: '123',
expiry_month: 12,
expiry_year: 2025
});
// OIDC authorization flow
const authUrl = await oidc.buildAuthorizationUrl({
client_id: 'my-app',
redirect_uri: 'https://myapp.com/callback',
scope: 'openid profile email'
});
// Exchange authorization code for tokens
const tokens = await oidc.exchangeCode('auth_code_here', 'code_verifier');
```
## Security Implementation
### PCI DSS Compliance
- **Tokenization**: Cards are immediately tokenized, raw data never stored
- **Encryption**: AES-256-GCM for all sensitive data at rest
- **Masking**: Card numbers always masked except last 4 digits
- **Audit Logging**: Complete audit trail for compliance
- **CVV Handling**: CVV never stored, only validated
### Transaction Security
- **Signing**: HMAC-SHA256 signatures on all transactions
- **Verification**: Signature verification before processing
- **Tamper Detection**: Any modification invalidates transaction
- **Idempotency**: Duplicate transaction prevention
### Authentication Security
- **JWT Signing**: RS256 with 2048-bit RSA keys
- **PKCE**: Proof Key for Code Exchange for authorization flow
- **Token Expiration**: Configurable expiration (default 1 hour)
- **Refresh Tokens**: Secure refresh token rotation
## Testing
### Unit Tests
```bash
# Run unit tests (without WASM constraints)
go test ./cmd/motr/...
```
### Integration Tests
```bash
# Build WASM first
make motr-wasm
# Run integration tests
cd cmd/motr
GOOS=js GOARCH=wasm go test -v
```
### Test Coverage
- ✅ Payment processing flows
- ✅ Card validation (Luhn, CVV, expiry)
- ✅ Tokenization and encryption
- ✅ Transaction signing/verification
- ✅ OIDC discovery and flows
- ✅ JWT generation/validation
- ✅ Rate limiting
- ✅ Security headers
- ✅ PCI compliance features
## Performance
### Bundle Size
- WASM module: ~3-4MB (production build)
- Service Worker: ~10KB
- TypeScript client: ~25KB (minified)
### Optimization
- Built with `-ldflags="-s -w"` for size reduction
- Gzip compression reduces transfer to ~1MB
- Lazy loading recommended for optimal performance
### Benchmarks
- Payment processing: <100ms average
- Token generation: <50ms
- Card validation: <10ms
- Encryption/decryption: <20ms
## Browser Compatibility
| Feature | Chrome | Firefox | Safari | Edge |
|---------|--------|---------|--------|------|
| Service Workers | 45+ | 44+ | 11.1+ | 17+ |
| WebAssembly | 57+ | 52+ | 11+ | 16+ |
| Payment Handler | 68+ | - | - | 79+ |
| Full Support | 68+ | 52+* | 11.1+* | 79+ |
*Payment Handler API has limited support
## Configuration
### Environment Variables
```javascript
// Configure in service worker
const config = {
issuer: 'https://motor.sonr.io',
rateLimit: 100, // requests per minute
rateWindow: 60000, // milliseconds
tokenExpiry: 3600, // seconds
allowedOrigins: ['https://localhost:3000']
};
```
### Security Settings
- Rate limiting: Configurable per-client limits
- CORS: Configurable allowed origins
- CSP: Customizable content security policy
- Token expiry: Adjustable for different use cases
## Development
### Prerequisites
- Go 1.21+ (1.23+ recommended)
- Modern browser with Service Worker support
- HTTPS or localhost (Service Workers requirement)
### Local Development
```bash
# Build WASM module
make motr-wasm
# Start local server (example)
cd packages/es/src/plugins/motor
python3 -m http.server 8080 --bind localhost
# Access at https://localhost:8080
```
### Debugging
- Browser DevTools: Network tab for API inspection
- Service Worker: Application tab for SW debugging
- Console: WASM logs and errors
- Payment Handler: chrome://settings/content/paymentHandler
## Production Deployment
### Best Practices
1. **HTTPS Required**: Service Workers only work over HTTPS
2. **Cache Strategy**: Implement proper cache headers
3. **Error Handling**: Comprehensive error logging
4. **Monitoring**: Track payment success rates
5. **Compliance**: Regular PCI DSS audits
### Deployment Checklist
- [ ] Configure production issuer URL
- [ ] Set appropriate rate limits
- [ ] Configure allowed origins
- [ ] Enable production encryption keys
- [ ] Set up monitoring and alerting
- [ ] Configure backup payment processors
- [ ] Implement fraud detection rules
- [ ] Schedule security audits
## Troubleshooting
### Common Issues
#### Service Worker Not Registering
- Ensure HTTPS or localhost
- Check browser compatibility
- Verify WASM file path
#### Payment Processing Errors
- Validate card details format
- Check rate limiting
- Verify origin is allowed
#### OIDC Flow Issues
- Ensure redirect URI matches
- Check PKCE implementation
- Verify token expiration
### Debug Mode
Enable debug logging in the service worker:
```javascript
// motor-worker.js
const DEBUG = true;
```
## License
This implementation is part of the Sonr project and follows the same license terms.
## Support
For issues, questions, or contributions:
- GitHub Issues: https://github.com/sonr-io/sonr/issues
- Documentation: https://docs.sonr.io
- Security: security@sonr.io (for security vulnerabilities)
-10
View File
@@ -1,10 +0,0 @@
module motr
go 1.24.7
require github.com/go-sonr/wasm-http-server/v3 v3.0.0
require (
github.com/hack-pad/safejs v0.1.1 // indirect
github.com/nlepage/go-js-promise v1.0.0 // indirect
)
-6
View File
@@ -1,6 +0,0 @@
github.com/go-sonr/wasm-http-server/v3 v3.0.0 h1:DY/XaJD0jfKlvpVlOTqyU5b+SRVOulR5+zOye0LK0o0=
github.com/go-sonr/wasm-http-server/v3 v3.0.0/go.mod h1:97QCYR5OlAEWeKeeIKCMZqCOIHqJakyTIFu0sbwDSJ8=
github.com/hack-pad/safejs v0.1.1 h1:d5qPO0iQ7h2oVtpzGnLExE+Wn9AtytxIfltcS2b9KD8=
github.com/hack-pad/safejs v0.1.1/go.mod h1:HdS+bKF1NrE72VoXZeWzxFOVQVUSqZJAG0xNCnb+Tio=
github.com/nlepage/go-js-promise v1.0.0 h1:K7OmJ3+0BgWJ2LfXchg2sI6RDr7AW/KWR8182epFwGQ=
github.com/nlepage/go-js-promise v1.0.0/go.mod h1:bdOP0wObXu34euibyK39K1hoBCtlgTKXGc56AGflaRo=
-446
View File
@@ -1,446 +0,0 @@
//go:build js && wasm
// +build js,wasm
package main
import (
"encoding/json"
"net/http"
"strings"
"time"
)
// Health & Status Handlers
// handleHealth returns service health status
func handleHealth(w http.ResponseWriter, r *http.Request) {
if r.Method == "OPTIONS" {
handleCORS(w)
return
}
writeJSON(w, http.StatusOK, map[string]interface{}{
"status": "healthy",
"service": "motor-gateway",
"timestamp": time.Now().Unix(),
})
}
// handleStatus returns detailed service status
func handleStatus(w http.ResponseWriter, r *http.Request) {
if r.Method == "OPTIONS" {
handleCORS(w)
return
}
writeJSON(w, http.StatusOK, map[string]interface{}{
"status": "operational",
"version": "1.0.0",
"services": map[string]string{
"payment_gateway": "active",
"oidc_provider": "active",
},
"uptime": time.Now().Unix(),
})
}
// W3C Payment Handler API Handlers
// handlePaymentInstruments returns available payment instruments
func handlePaymentInstruments(w http.ResponseWriter, r *http.Request) {
if r.Method == "OPTIONS" {
handleCORS(w)
return
}
if r.Method != "GET" {
writeError(w, http.StatusMethodNotAllowed, "Method not allowed")
return
}
instruments := paymentHandler.GetInstruments()
writeJSON(w, http.StatusOK, map[string]interface{}{
"instruments": instruments,
})
}
// handleCanMakePayment checks if payment can be made
func handleCanMakePayment(w http.ResponseWriter, r *http.Request) {
if r.Method == "OPTIONS" {
handleCORS(w)
return
}
if r.Method != "POST" {
writeError(w, http.StatusMethodNotAllowed, "Method not allowed")
return
}
var req struct {
MethodData []PaymentMethod `json:"methodData"`
}
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
writeError(w, http.StatusBadRequest, "Invalid request body")
return
}
canMakePayment := paymentHandler.CanMakePayment(req.MethodData)
writeJSON(w, http.StatusOK, map[string]interface{}{
"canMakePayment": canMakePayment,
})
}
// handlePaymentRequest handles W3C PaymentRequestEvent
func handlePaymentRequest(w http.ResponseWriter, r *http.Request) {
if r.Method == "OPTIONS" {
handleCORS(w)
return
}
if r.Method != "POST" {
writeError(w, http.StatusMethodNotAllowed, "Method not allowed")
return
}
// Parse payment request event
var reqData json.RawMessage
if err := json.NewDecoder(r.Body).Decode(&reqData); err != nil {
writeError(w, http.StatusBadRequest, "Invalid request body")
return
}
paymentReq, err := SerializePaymentRequest(reqData)
if err != nil {
writeError(w, http.StatusBadRequest, "Invalid payment request")
return
}
// Process payment request
tx, err := paymentHandler.ProcessPayment(paymentReq)
if err != nil {
writeError(w, http.StatusInternalServerError, "Payment processing failed")
return
}
// Return payment response
if tx.Response != nil {
writeJSON(w, http.StatusOK, tx.Response)
} else {
writeJSON(w, http.StatusAccepted, map[string]interface{}{
"transactionId": tx.ID,
"status": tx.Status,
})
}
}
// Payment Gateway Handlers
// handlePaymentProcess processes a payment transaction using W3C Payment Handler API
func handlePaymentProcess(w http.ResponseWriter, r *http.Request) {
if r.Method == "OPTIONS" {
handleCORS(w)
return
}
if r.Method != "POST" {
writeError(w, http.StatusMethodNotAllowed, "Method not allowed")
return
}
// Parse payment request
var reqData json.RawMessage
if err := json.NewDecoder(r.Body).Decode(&reqData); err != nil {
writeError(w, http.StatusBadRequest, "Invalid request body")
return
}
paymentReq, err := SerializePaymentRequest(reqData)
if err != nil {
writeError(w, http.StatusBadRequest, "Invalid payment request")
return
}
// Process payment
tx, err := paymentHandler.ProcessPayment(paymentReq)
if err != nil {
writeError(w, http.StatusInternalServerError, "Payment processing failed")
return
}
writeJSON(w, http.StatusOK, tx)
}
// handlePaymentValidate validates a payment method
func handlePaymentValidate(w http.ResponseWriter, r *http.Request) {
if r.Method == "OPTIONS" {
handleCORS(w)
return
}
if r.Method != "POST" {
writeError(w, http.StatusMethodNotAllowed, "Method not allowed")
return
}
// Parse validation request
var req struct {
Method string `json:"method"`
Data map[string]interface{} `json:"data"`
}
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
writeError(w, http.StatusBadRequest, "Invalid request body")
return
}
// Validate payment method
valid, err := paymentHandler.ValidatePaymentMethod(req.Method, req.Data)
if err != nil {
writeError(w, http.StatusInternalServerError, "Validation failed")
return
}
writeJSON(w, http.StatusOK, map[string]interface{}{
"valid": valid,
"method": req.Method,
"message": "Payment method validation complete",
})
}
// handlePaymentStatus returns payment transaction status
func handlePaymentStatus(w http.ResponseWriter, r *http.Request) {
if r.Method == "OPTIONS" {
handleCORS(w)
return
}
if r.Method != "GET" {
writeError(w, http.StatusMethodNotAllowed, "Method not allowed")
return
}
// Extract transaction ID from path
txID := strings.TrimPrefix(r.URL.Path, "/api/payment/status/")
if txID == "" {
writeError(w, http.StatusBadRequest, "Transaction ID required")
return
}
// Get transaction from handler
tx, exists := paymentHandler.GetTransaction(txID)
if !exists {
writeError(w, http.StatusNotFound, "Transaction not found")
return
}
writeJSON(w, http.StatusOK, tx)
}
// handlePaymentRefund processes a refund
func handlePaymentRefund(w http.ResponseWriter, r *http.Request) {
if r.Method == "OPTIONS" {
handleCORS(w)
return
}
if r.Method != "POST" {
writeError(w, http.StatusMethodNotAllowed, "Method not allowed")
return
}
// TODO: Implement refund processing
writeJSON(w, http.StatusOK, map[string]interface{}{
"refund_id": "ref_" + generateID(),
"status": "processing",
"message": "Refund initiated",
})
}
// OIDC Handlers
// handleOIDCDiscovery returns OIDC discovery document
func handleOIDCDiscovery(w http.ResponseWriter, r *http.Request) {
if r.Method == "OPTIONS" {
handleCORS(w)
return
}
discovery := oidcProvider.GetDiscovery()
writeJSON(w, http.StatusOK, discovery)
}
// handleJWKS returns JSON Web Key Set
func handleJWKS(w http.ResponseWriter, r *http.Request) {
if r.Method == "OPTIONS" {
handleCORS(w)
return
}
jwk := jwtManager.GetPublicKeyJWK()
writeJSON(w, http.StatusOK, map[string]interface{}{
"keys": []map[string]interface{}{jwk},
})
}
// handleAuthorize handles authorization requests
func handleAuthorize(w http.ResponseWriter, r *http.Request) {
if r.Method == "OPTIONS" {
handleCORS(w)
return
}
if r.Method != "GET" && r.Method != "POST" {
writeError(w, http.StatusMethodNotAllowed, "Method not allowed")
return
}
// Parse authorization request
clientID := r.FormValue("client_id")
redirectURI := r.FormValue("redirect_uri")
responseType := r.FormValue("response_type")
scope := r.FormValue("scope")
state := r.FormValue("state")
nonce := r.FormValue("nonce")
codeChallenge := r.FormValue("code_challenge")
codeChallengeMethod := r.FormValue("code_challenge_method")
// Validate request
if clientID == "" || redirectURI == "" || responseType == "" {
writeError(w, http.StatusBadRequest, "Missing required parameters")
return
}
// For demo, auto-approve with test user
userID := "test-user"
// Generate authorization code
authCode, err := oidcProvider.GenerateAuthorizationCode(
clientID, redirectURI, scope, state, nonce, userID,
codeChallenge, codeChallengeMethod,
)
if err != nil {
writeError(w, http.StatusBadRequest, err.Error())
return
}
// Return authorization code
writeJSON(w, http.StatusOK, map[string]interface{}{
"code": authCode.Code,
"state": state,
"redirect_uri": redirectURI,
})
}
// handleToken handles token requests
func handleToken(w http.ResponseWriter, r *http.Request) {
if r.Method == "OPTIONS" {
handleCORS(w)
return
}
if r.Method != "POST" {
writeError(w, http.StatusMethodNotAllowed, "Method not allowed")
return
}
// Parse token request
var req TokenRequest
req.GrantType = r.FormValue("grant_type")
req.Code = r.FormValue("code")
req.RedirectURI = r.FormValue("redirect_uri")
req.ClientID = r.FormValue("client_id")
req.ClientSecret = r.FormValue("client_secret")
req.RefreshToken = r.FormValue("refresh_token")
req.Scope = r.FormValue("scope")
req.CodeVerifier = r.FormValue("code_verifier")
// Handle based on grant type
var resp *TokenResponse
var err error
switch req.GrantType {
case "authorization_code":
resp, err = oidcProvider.ExchangeCode(&req)
case "refresh_token":
// TODO: Implement refresh token flow
writeError(w, http.StatusNotImplemented, "Refresh token not yet implemented")
return
default:
writeError(w, http.StatusBadRequest, "Unsupported grant type")
return
}
if err != nil {
writeError(w, http.StatusBadRequest, err.Error())
return
}
writeJSON(w, http.StatusOK, resp)
}
// handleUserInfo returns user information
func handleUserInfo(w http.ResponseWriter, r *http.Request) {
if r.Method == "OPTIONS" {
handleCORS(w)
return
}
if r.Method != "GET" && r.Method != "POST" {
writeError(w, http.StatusMethodNotAllowed, "Method not allowed")
return
}
// Get bearer token from Authorization header
authHeader := r.Header.Get("Authorization")
if authHeader == "" {
writeError(w, http.StatusUnauthorized, "Missing authorization header")
return
}
// Extract token
parts := strings.Split(authHeader, " ")
if len(parts) != 2 || parts[0] != "Bearer" {
writeError(w, http.StatusUnauthorized, "Invalid authorization header")
return
}
accessToken := parts[1]
// Get user info
userInfo, err := oidcProvider.GetUserInfo(accessToken)
if err != nil {
writeError(w, http.StatusUnauthorized, err.Error())
return
}
writeJSON(w, http.StatusOK, userInfo)
}
// Helper Functions
// handleCORS handles CORS preflight requests
func handleCORS(w http.ResponseWriter) {
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization")
w.WriteHeader(http.StatusOK)
}
// writeJSON writes JSON response
func writeJSON(w http.ResponseWriter, status int, data interface{}) {
w.Header().Set("Content-Type", "application/json")
w.Header().Set("Access-Control-Allow-Origin", "*")
w.WriteHeader(status)
json.NewEncoder(w).Encode(data)
}
// writeError writes error response
func writeError(w http.ResponseWriter, status int, message string) {
writeJSON(w, status, map[string]string{"error": message})
}
// generateID generates a simple ID
func generateID() string {
return time.Now().Format("20060102150405")
}
-405
View File
@@ -1,405 +0,0 @@
//go:build js && wasm
// +build js,wasm
package main
import (
"bytes"
"encoding/json"
"net/http"
"net/http/httptest"
"testing"
"time"
)
// TestHealthEndpoint tests the health check endpoint
func TestHealthEndpoint(t *testing.T) {
req := httptest.NewRequest("GET", "/health", nil)
w := httptest.NewRecorder()
handleHealth(w, req)
if w.Code != http.StatusOK {
t.Errorf("Expected status 200, got %d", w.Code)
}
var response map[string]interface{}
if err := json.NewDecoder(w.Body).Decode(&response); err != nil {
t.Fatalf("Failed to decode response: %v", err)
}
if response["status"] != "healthy" {
t.Errorf("Expected status healthy, got %v", response["status"])
}
}
// TestPaymentInstruments tests getting payment instruments
func TestPaymentInstruments(t *testing.T) {
req := httptest.NewRequest("GET", "/payment/instruments", nil)
w := httptest.NewRecorder()
handlePaymentInstruments(w, req)
if w.Code != http.StatusOK {
t.Errorf("Expected status 200, got %d", w.Code)
}
var instruments []map[string]interface{}
if err := json.NewDecoder(w.Body).Decode(&instruments); err != nil {
t.Fatalf("Failed to decode response: %v", err)
}
if len(instruments) == 0 {
t.Error("Expected at least one payment instrument")
}
}
// TestCanMakePayment tests payment capability check
func TestCanMakePayment(t *testing.T) {
payload := map[string]interface{}{
"origin": "https://localhost:3000",
"methodData": []map[string]interface{}{
{
"supportedMethods": "https://motor.sonr.io/pay",
},
},
}
body, _ := json.Marshal(payload)
req := httptest.NewRequest("POST", "/payment/canmakepayment", bytes.NewBuffer(body))
req.Header.Set("Content-Type", "application/json")
w := httptest.NewRecorder()
handleCanMakePayment(w, req)
if w.Code != http.StatusOK {
t.Errorf("Expected status 200, got %d", w.Code)
}
var response map[string]interface{}
if err := json.NewDecoder(w.Body).Decode(&response); err != nil {
t.Fatalf("Failed to decode response: %v", err)
}
if response["canMakePayment"] != true {
t.Errorf("Expected canMakePayment to be true")
}
}
// TestProcessPayment tests payment processing with security
func TestProcessPayment(t *testing.T) {
// Initialize payment security
InitializePaymentSecurity()
payload := map[string]interface{}{
"origin": "https://localhost:3000",
"topOrigin": "https://localhost:3000",
"paymentRequestId": "test-request-123",
"methodData": []map[string]interface{}{
{
"supportedMethods": "https://motor.sonr.io/pay",
},
},
"details": map[string]interface{}{
"total": map[string]interface{}{
"label": "Test Payment",
"amount": map[string]interface{}{
"currency": "USD",
"value": "100.00",
},
},
},
}
body, _ := json.Marshal(payload)
req := httptest.NewRequest("POST", "/api/payment/process", bytes.NewBuffer(body))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Origin", "https://localhost:3000")
w := httptest.NewRecorder()
handleProcessPayment(w, req)
if w.Code != http.StatusOK {
t.Errorf("Expected status 200, got %d", w.Code)
}
var response map[string]interface{}
if err := json.NewDecoder(w.Body).Decode(&response); err != nil {
t.Fatalf("Failed to decode response: %v", err)
}
if response["paymentId"] == "" {
t.Error("Expected payment ID in response")
}
if response["status"] != "pending" {
t.Errorf("Expected status pending, got %v", response["status"])
}
}
// TestCardTokenization tests PCI-compliant card tokenization
func TestCardTokenization(t *testing.T) {
// Initialize payment security
InitializePaymentSecurity()
// Test valid card
token, err := TokenizeCard("4111111111111111", "123", 12, 2025)
if err != nil {
t.Fatalf("Failed to tokenize valid card: %v", err)
}
if token == "" {
t.Error("Expected token to be generated")
}
// Test invalid card number
_, err = TokenizeCard("1234567890123456", "123", 12, 2025)
if err == nil {
t.Error("Expected error for invalid card number")
}
// Test expired card
_, err = TokenizeCard("4111111111111111", "123", 1, 2020)
if err == nil {
t.Error("Expected error for expired card")
}
}
// TestTransactionSigning tests transaction signature verification
func TestTransactionSigning(t *testing.T) {
// Initialize payment security
InitializePaymentSecurity()
txData := map[string]interface{}{
"id": "test-tx-123",
"amount": "100.00",
"currency": "USD",
"method": "card",
"timestamp": time.Now().Unix(),
}
// Sign transaction
signature, err := SignTransaction(txData)
if err != nil {
t.Fatalf("Failed to sign transaction: %v", err)
}
if signature == "" {
t.Error("Expected signature to be generated")
}
// Verify signature
valid := VerifyTransactionSignature(txData, signature)
if !valid {
t.Error("Expected signature to be valid")
}
// Test invalid signature
invalid := VerifyTransactionSignature(txData, "invalid-signature")
if invalid {
t.Error("Expected invalid signature to fail verification")
}
}
// TestOIDCDiscovery tests OIDC discovery endpoint
func TestOIDCDiscovery(t *testing.T) {
req := httptest.NewRequest("GET", "/.well-known/openid-configuration", nil)
w := httptest.NewRecorder()
handleOIDCDiscovery(w, req)
if w.Code != http.StatusOK {
t.Errorf("Expected status 200, got %d", w.Code)
}
var config map[string]interface{}
if err := json.NewDecoder(w.Body).Decode(&config); err != nil {
t.Fatalf("Failed to decode response: %v", err)
}
// Check required OIDC fields
requiredFields := []string{
"issuer",
"authorization_endpoint",
"token_endpoint",
"userinfo_endpoint",
"jwks_uri",
}
for _, field := range requiredFields {
if _, exists := config[field]; !exists {
t.Errorf("Missing required OIDC field: %s", field)
}
}
}
// TestJWKS tests JWKS endpoint
func TestJWKS(t *testing.T) {
req := httptest.NewRequest("GET", "/.well-known/jwks.json", nil)
w := httptest.NewRecorder()
handleJWKS(w, req)
if w.Code != http.StatusOK {
t.Errorf("Expected status 200, got %d", w.Code)
}
var jwks map[string]interface{}
if err := json.NewDecoder(w.Body).Decode(&jwks); err != nil {
t.Fatalf("Failed to decode response: %v", err)
}
keys, ok := jwks["keys"].([]interface{})
if !ok || len(keys) == 0 {
t.Error("Expected at least one key in JWKS")
}
}
// TestRateLimiting tests rate limiting functionality
func TestRateLimiting(t *testing.T) {
// Initialize with low rate limit for testing
securityConfig.RateLimit = 5
securityConfig.RateWindow = time.Second
rateLimiter = NewRateLimiter(5, time.Second)
// Make requests up to the limit
for i := 0; i < 5; i++ {
req := httptest.NewRequest("GET", "/health", nil)
req.Header.Set("Origin", "test-client")
w := httptest.NewRecorder()
SecurityMiddleware(handleHealth)(w, req)
if w.Code != http.StatusOK {
t.Errorf("Request %d: Expected status 200, got %d", i+1, w.Code)
}
}
// Next request should be rate limited
req := httptest.NewRequest("GET", "/health", nil)
req.Header.Set("Origin", "test-client")
w := httptest.NewRecorder()
SecurityMiddleware(handleHealth)(w, req)
if w.Code != http.StatusTooManyRequests {
t.Errorf("Expected rate limit (429), got %d", w.Code)
}
// Wait for rate limit window to reset
time.Sleep(time.Second + 100*time.Millisecond)
// Should work again
req = httptest.NewRequest("GET", "/health", nil)
req.Header.Set("Origin", "test-client")
w = httptest.NewRecorder()
SecurityMiddleware(handleHealth)(w, req)
if w.Code != http.StatusOK {
t.Errorf("After reset: Expected status 200, got %d", w.Code)
}
}
// TestSecurityHeaders tests security headers are properly set
func TestSecurityHeaders(t *testing.T) {
req := httptest.NewRequest("GET", "/health", nil)
w := httptest.NewRecorder()
SecurityMiddleware(handleHealth)(w, req)
// Check security headers
headers := map[string]string{
"X-Content-Type-Options": "nosniff",
"X-Frame-Options": "DENY",
"X-XSS-Protection": "1; mode=block",
"Referrer-Policy": "strict-origin-when-cross-origin",
}
for header, expected := range headers {
actual := w.Header().Get(header)
if actual != expected {
t.Errorf("Header %s: expected %s, got %s", header, expected, actual)
}
}
// Check CSP is present
csp := w.Header().Get("Content-Security-Policy")
if csp == "" {
t.Error("Expected Content-Security-Policy header")
}
}
// TestPCICompliance tests PCI compliance audit logging
func TestPCICompliance(t *testing.T) {
// Initialize payment security
InitializePaymentSecurity()
// Log some actions
pciCompliance.LogAction("TEST_ACTION", "user123", "resource456", "SUCCESS", "127.0.0.1")
// Get audit log
logs := pciCompliance.GetAuditLog(10)
if len(logs) == 0 {
t.Error("Expected audit log entries")
}
// Check last entry
lastLog := logs[len(logs)-1]
if lastLog.Action != "TEST_ACTION" {
t.Errorf("Expected action TEST_ACTION, got %s", lastLog.Action)
}
if lastLog.UserID != "user123" {
t.Errorf("Expected user ID user123, got %s", lastLog.UserID)
}
}
// TestDataEncryption tests sensitive data encryption
func TestDataEncryption(t *testing.T) {
// Initialize payment security
InitializePaymentSecurity()
sensitiveData := "4111-1111-1111-1111"
// Encrypt data
encrypted, err := EncryptSensitiveData(sensitiveData)
if err != nil {
t.Fatalf("Failed to encrypt data: %v", err)
}
if encrypted == sensitiveData {
t.Error("Encrypted data should not match plaintext")
}
// Decrypt data
decrypted, err := DecryptSensitiveData(encrypted)
if err != nil {
t.Fatalf("Failed to decrypt data: %v", err)
}
if decrypted != sensitiveData {
t.Errorf("Decrypted data doesn't match original: got %s, want %s", decrypted, sensitiveData)
}
}
// TestCardMasking tests card number masking
func TestCardMasking(t *testing.T) {
testCases := []struct {
input string
expected string
}{
{"4111111111111111", "**** **** **** 1111"},
{"5500000000000004", "**** **** **** 0004"},
{"340000000000009", "********** 00009"},
{"123", "123"}, // Too short to mask
}
for _, tc := range testCases {
masked := MaskCardNumber(tc.input)
if masked != tc.expected {
t.Errorf("MaskCardNumber(%s): got %s, want %s", tc.input, masked, tc.expected)
}
}
}
-273
View File
@@ -1,273 +0,0 @@
//go:build js && wasm
// +build js,wasm
package main
import (
"crypto"
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"crypto/x509"
"encoding/base64"
"encoding/json"
"encoding/pem"
"fmt"
"strings"
"time"
)
// JWTManager handles JWT token operations
type JWTManager struct {
privateKey *rsa.PrivateKey
publicKey *rsa.PublicKey
kid string
issuer string
}
// JWTHeader represents JWT header
type JWTHeader struct {
Alg string `json:"alg"`
Typ string `json:"typ"`
Kid string `json:"kid,omitempty"`
}
// JWTClaims represents standard JWT claims
type JWTClaims struct {
Issuer string `json:"iss,omitempty"`
Subject string `json:"sub,omitempty"`
Audience interface{} `json:"aud,omitempty"` // Can be string or []string
Expiration int64 `json:"exp,omitempty"`
NotBefore int64 `json:"nbf,omitempty"`
IssuedAt int64 `json:"iat,omitempty"`
JWTID string `json:"jti,omitempty"`
Nonce string `json:"nonce,omitempty"`
Extra map[string]interface{} `json:"-"`
}
// IDToken represents an OpenID Connect ID token
type IDToken struct {
JWTClaims
AuthTime int64 `json:"auth_time,omitempty"`
Nonce string `json:"nonce,omitempty"`
ACR string `json:"acr,omitempty"`
AMR []string `json:"amr,omitempty"`
AZP string `json:"azp,omitempty"`
Name string `json:"name,omitempty"`
GivenName string `json:"given_name,omitempty"`
FamilyName string `json:"family_name,omitempty"`
Email string `json:"email,omitempty"`
EmailVerified bool `json:"email_verified,omitempty"`
}
// Global JWT manager instance
var jwtManager *JWTManager
// InitJWTManager initializes the JWT manager
func InitJWTManager() error {
// Generate RSA key pair
privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
return fmt.Errorf("failed to generate RSA key: %w", err)
}
jwtManager = &JWTManager{
privateKey: privateKey,
publicKey: &privateKey.PublicKey,
kid: "motor-key-1",
issuer: "https://motor.sonr.io",
}
return nil
}
// GenerateToken generates a JWT token
func (m *JWTManager) GenerateToken(claims JWTClaims) (string, error) {
// Set standard claims
if claims.Issuer == "" {
claims.Issuer = m.issuer
}
if claims.IssuedAt == 0 {
claims.IssuedAt = time.Now().Unix()
}
if claims.Expiration == 0 {
claims.Expiration = time.Now().Add(1 * time.Hour).Unix()
}
// Create header
header := JWTHeader{
Alg: "RS256",
Typ: "JWT",
Kid: m.kid,
}
// Encode header
headerJSON, _ := json.Marshal(header)
headerEncoded := base64.RawURLEncoding.EncodeToString(headerJSON)
// Encode claims
claimsJSON, _ := json.Marshal(claims)
claimsEncoded := base64.RawURLEncoding.EncodeToString(claimsJSON)
// Create signature
message := headerEncoded + "." + claimsEncoded
hash := sha256.Sum256([]byte(message))
signature, err := rsa.SignPKCS1v15(rand.Reader, m.privateKey, crypto.SHA256, hash[:])
if err != nil {
return "", err
}
signatureEncoded := base64.RawURLEncoding.EncodeToString(signature)
// Combine parts
token := message + "." + signatureEncoded
return token, nil
}
// GenerateIDToken generates an OpenID Connect ID token
func (m *JWTManager) GenerateIDToken(subject, audience, nonce string, extra map[string]interface{}) (string, error) {
idToken := IDToken{
JWTClaims: JWTClaims{
Issuer: m.issuer,
Subject: subject,
Audience: audience,
IssuedAt: time.Now().Unix(),
Expiration: time.Now().Add(1 * time.Hour).Unix(),
Nonce: nonce,
},
AuthTime: time.Now().Unix(),
Email: fmt.Sprintf("%s@motor.sonr.io", subject),
EmailVerified: true,
}
// Convert to claims
claims := JWTClaims{
Issuer: idToken.Issuer,
Subject: idToken.Subject,
Audience: idToken.Audience,
IssuedAt: idToken.IssuedAt,
Expiration: idToken.Expiration,
Nonce: idToken.Nonce,
Extra: map[string]interface{}{
"auth_time": idToken.AuthTime,
"email": idToken.Email,
"email_verified": idToken.EmailVerified,
},
}
// Add extra claims
for k, v := range extra {
claims.Extra[k] = v
}
return m.GenerateToken(claims)
}
// ValidateToken validates a JWT token
func (m *JWTManager) ValidateToken(tokenString string) (*JWTClaims, error) {
// Split token
parts := strings.Split(tokenString, ".")
if len(parts) != 3 {
return nil, fmt.Errorf("invalid token format")
}
// Decode header
headerJSON, err := base64.RawURLEncoding.DecodeString(parts[0])
if err != nil {
return nil, fmt.Errorf("failed to decode header: %w", err)
}
var header JWTHeader
if err := json.Unmarshal(headerJSON, &header); err != nil {
return nil, fmt.Errorf("failed to parse header: %w", err)
}
// Verify algorithm
if header.Alg != "RS256" {
return nil, fmt.Errorf("unsupported algorithm: %s", header.Alg)
}
// Decode claims
claimsJSON, err := base64.RawURLEncoding.DecodeString(parts[1])
if err != nil {
return nil, fmt.Errorf("failed to decode claims: %w", err)
}
var claims JWTClaims
if err := json.Unmarshal(claimsJSON, &claims); err != nil {
return nil, fmt.Errorf("failed to parse claims: %w", err)
}
// Verify signature
message := parts[0] + "." + parts[1]
signature, err := base64.RawURLEncoding.DecodeString(parts[2])
if err != nil {
return nil, fmt.Errorf("failed to decode signature: %w", err)
}
hash := sha256.Sum256([]byte(message))
if err := rsa.VerifyPKCS1v15(m.publicKey, crypto.SHA256, hash[:], signature); err != nil {
return nil, fmt.Errorf("invalid signature: %w", err)
}
// Verify expiration
if claims.Expiration > 0 && time.Now().Unix() > claims.Expiration {
return nil, fmt.Errorf("token expired")
}
// Verify not before
if claims.NotBefore > 0 && time.Now().Unix() < claims.NotBefore {
return nil, fmt.Errorf("token not yet valid")
}
return &claims, nil
}
// GetPublicKeyJWK returns the public key in JWK format
func (m *JWTManager) GetPublicKeyJWK() map[string]interface{} {
// Get modulus and exponent
n := base64.RawURLEncoding.EncodeToString(m.publicKey.N.Bytes())
e := base64.RawURLEncoding.EncodeToString([]byte{1, 0, 1}) // 65537
return map[string]interface{}{
"kty": "RSA",
"use": "sig",
"kid": m.kid,
"alg": "RS256",
"n": n,
"e": e,
}
}
// GetPublicKeyPEM returns the public key in PEM format
func (m *JWTManager) GetPublicKeyPEM() string {
pubKeyBytes, _ := x509.MarshalPKIXPublicKey(m.publicKey)
pubKeyPEM := pem.EncodeToMemory(&pem.Block{
Type: "PUBLIC KEY",
Bytes: pubKeyBytes,
})
return string(pubKeyPEM)
}
// GenerateAccessToken generates an access token
func (m *JWTManager) GenerateAccessToken(subject, scope string) (string, error) {
claims := JWTClaims{
Subject: subject,
Extra: map[string]interface{}{
"scope": scope,
"token_type": "Bearer",
},
}
return m.GenerateToken(claims)
}
// GenerateRefreshToken generates a refresh token
func (m *JWTManager) GenerateRefreshToken(subject string) (string, error) {
claims := JWTClaims{
Subject: subject,
Expiration: time.Now().Add(30 * 24 * time.Hour).Unix(), // 30 days
Extra: map[string]interface{}{
"token_type": "refresh",
},
}
return m.GenerateToken(claims)
}
-50
View File
@@ -1,50 +0,0 @@
//go:build js && wasm
// +build js,wasm
package main
import (
"log"
"net/http"
wasmhttp "github.com/go-sonr/wasm-http-server/v3"
)
func main() {
// Set up HTTP routes
setupRoutes()
// Start the WASM HTTP server
log.Println("Motor Payment Gateway & OIDC Server starting...")
log.Println("Available endpoints:")
log.Println(" Health: /health, /status")
log.Println(" Payment API: /api/payment/*")
log.Println(" OIDC: /.well-known/*, /authorize, /token, /userinfo")
wasmhttp.Serve(nil)
}
// setupRoutes configures all HTTP routes with security middleware
func setupRoutes() {
// Health and status endpoints (no rate limiting)
http.HandleFunc("/health", handleHealth)
http.HandleFunc("/status", handleStatus)
// W3C Payment Handler API endpoints with security
http.HandleFunc("/payment/instruments", SecurityMiddleware(handlePaymentInstruments))
http.HandleFunc("/payment/canmakepayment", SecurityMiddleware(handleCanMakePayment))
http.HandleFunc("/payment/paymentrequest", SecurityMiddleware(handlePaymentRequest))
// Payment Gateway endpoints with security
http.HandleFunc("/api/payment/process", SecurityMiddleware(handlePaymentProcess))
http.HandleFunc("/api/payment/validate", SecurityMiddleware(handlePaymentValidate))
http.HandleFunc("/api/payment/status/", SecurityMiddleware(handlePaymentStatus))
http.HandleFunc("/api/payment/refund", SecurityMiddleware(handlePaymentRefund))
// OIDC endpoints with security
http.HandleFunc("/.well-known/openid-configuration", handleOIDCDiscovery) // No rate limit for discovery
http.HandleFunc("/.well-known/jwks.json", handleJWKS) // No rate limit for JWKS
http.HandleFunc("/authorize", SecurityMiddleware(handleAuthorize))
http.HandleFunc("/token", SecurityMiddleware(handleToken))
http.HandleFunc("/userinfo", SecurityMiddleware(handleUserInfo))
}
-364
View File
@@ -1,364 +0,0 @@
//go:build js && wasm
// +build js,wasm
package main
import (
"crypto/rand"
"encoding/base64"
"fmt"
"strings"
"sync"
"time"
)
// OIDCProvider manages OpenID Connect operations
type OIDCProvider struct {
mu sync.RWMutex
issuer string
authCodes map[string]*AuthorizationCode
accessTokens map[string]*AccessToken
refreshTokens map[string]*RefreshToken
clients map[string]*OIDCClient
users map[string]*User
}
// AuthorizationCode represents an authorization code
type AuthorizationCode struct {
Code string
ClientID string
RedirectURI string
Scope string
State string
Nonce string
UserID string
ExpiresAt time.Time
CodeChallenge string
CodeChallengeMethod string
}
// AccessToken represents an access token
type AccessToken struct {
Token string
ClientID string
UserID string
Scope string
ExpiresAt time.Time
}
// RefreshToken represents a refresh token
type RefreshToken struct {
Token string
ClientID string
UserID string
Scope string
ExpiresAt time.Time
}
// OIDCClient represents an OIDC client application
type OIDCClient struct {
ClientID string
ClientSecret string
RedirectURIs []string
GrantTypes []string
ResponseTypes []string
Scopes []string
Name string
}
// User represents a user
type User struct {
ID string
Username string
Email string
EmailVerified bool
Name string
GivenName string
FamilyName string
}
// OIDCDiscovery represents OIDC discovery document
type OIDCDiscovery struct {
Issuer string `json:"issuer"`
AuthorizationEndpoint string `json:"authorization_endpoint"`
TokenEndpoint string `json:"token_endpoint"`
UserInfoEndpoint string `json:"userinfo_endpoint"`
JWKSUri string `json:"jwks_uri"`
RegistrationEndpoint string `json:"registration_endpoint,omitempty"`
ScopesSupported []string `json:"scopes_supported"`
ResponseTypesSupported []string `json:"response_types_supported"`
ResponseModesSupported []string `json:"response_modes_supported,omitempty"`
GrantTypesSupported []string `json:"grant_types_supported"`
ACRValuesSupported []string `json:"acr_values_supported,omitempty"`
SubjectTypesSupported []string `json:"subject_types_supported"`
IDTokenSigningAlgValuesSupported []string `json:"id_token_signing_alg_values_supported"`
TokenEndpointAuthMethodsSupported []string `json:"token_endpoint_auth_methods_supported"`
ClaimsSupported []string `json:"claims_supported"`
CodeChallengeMethodsSupported []string `json:"code_challenge_methods_supported"`
}
// TokenRequest represents a token request
type TokenRequest struct {
GrantType string `json:"grant_type"`
Code string `json:"code,omitempty"`
RedirectURI string `json:"redirect_uri,omitempty"`
ClientID string `json:"client_id"`
ClientSecret string `json:"client_secret,omitempty"`
RefreshToken string `json:"refresh_token,omitempty"`
Scope string `json:"scope,omitempty"`
CodeVerifier string `json:"code_verifier,omitempty"`
}
// TokenResponse represents a token response
type TokenResponse struct {
AccessToken string `json:"access_token"`
TokenType string `json:"token_type"`
ExpiresIn int `json:"expires_in"`
RefreshToken string `json:"refresh_token,omitempty"`
IDToken string `json:"id_token,omitempty"`
Scope string `json:"scope,omitempty"`
}
// Global OIDC provider instance
var oidcProvider = &OIDCProvider{
issuer: "https://motor.sonr.io",
authCodes: make(map[string]*AuthorizationCode),
accessTokens: make(map[string]*AccessToken),
refreshTokens: make(map[string]*RefreshToken),
clients: make(map[string]*OIDCClient),
users: make(map[string]*User),
}
// Initialize OIDC provider
func init() {
// Initialize JWT manager
InitJWTManager()
// Add default client for testing
oidcProvider.clients["motor-client"] = &OIDCClient{
ClientID: "motor-client",
ClientSecret: "motor-secret",
RedirectURIs: []string{"https://localhost:3000/callback", "http://localhost:3000/callback"},
GrantTypes: []string{"authorization_code", "refresh_token"},
ResponseTypes: []string{"code", "token", "id_token"},
Scopes: []string{"openid", "profile", "email"},
Name: "Motor Test Client",
}
// Add default user for testing
oidcProvider.users["test-user"] = &User{
ID: "test-user",
Username: "testuser",
Email: "test@motor.sonr.io",
EmailVerified: true,
Name: "Test User",
GivenName: "Test",
FamilyName: "User",
}
}
// GetDiscovery returns OIDC discovery document
func (p *OIDCProvider) GetDiscovery() *OIDCDiscovery {
return &OIDCDiscovery{
Issuer: p.issuer,
AuthorizationEndpoint: "/authorize",
TokenEndpoint: "/token",
UserInfoEndpoint: "/userinfo",
JWKSUri: "/.well-known/jwks.json",
ScopesSupported: []string{
"openid", "profile", "email", "offline_access",
},
ResponseTypesSupported: []string{
"code", "token", "id_token", "code token", "code id_token", "token id_token", "code token id_token",
},
GrantTypesSupported: []string{
"authorization_code", "implicit", "refresh_token",
},
SubjectTypesSupported: []string{"public"},
IDTokenSigningAlgValuesSupported: []string{"RS256"},
TokenEndpointAuthMethodsSupported: []string{
"client_secret_basic", "client_secret_post",
},
ClaimsSupported: []string{
"sub", "name", "given_name", "family_name", "email", "email_verified",
},
CodeChallengeMethodsSupported: []string{"plain", "S256"},
}
}
// GenerateAuthorizationCode generates an authorization code
func (p *OIDCProvider) GenerateAuthorizationCode(clientID, redirectURI, scope, state, nonce, userID string, codeChallenge, codeChallengeMethod string) (*AuthorizationCode, error) {
p.mu.Lock()
defer p.mu.Unlock()
// Validate client
client, exists := p.clients[clientID]
if !exists {
return nil, fmt.Errorf("invalid client_id")
}
// Validate redirect URI
validRedirect := false
for _, uri := range client.RedirectURIs {
if uri == redirectURI {
validRedirect = true
break
}
}
if !validRedirect {
return nil, fmt.Errorf("invalid redirect_uri")
}
// Generate code
code := generateRandomString(32)
authCode := &AuthorizationCode{
Code: code,
ClientID: clientID,
RedirectURI: redirectURI,
Scope: scope,
State: state,
Nonce: nonce,
UserID: userID,
ExpiresAt: time.Now().Add(10 * time.Minute),
CodeChallenge: codeChallenge,
CodeChallengeMethod: codeChallengeMethod,
}
p.authCodes[code] = authCode
return authCode, nil
}
// ExchangeCode exchanges authorization code for tokens
func (p *OIDCProvider) ExchangeCode(req *TokenRequest) (*TokenResponse, error) {
p.mu.Lock()
defer p.mu.Unlock()
// Get authorization code
authCode, exists := p.authCodes[req.Code]
if !exists {
return nil, fmt.Errorf("invalid authorization code")
}
// Validate code hasn't expired
if time.Now().After(authCode.ExpiresAt) {
delete(p.authCodes, req.Code)
return nil, fmt.Errorf("authorization code expired")
}
// Validate client
if authCode.ClientID != req.ClientID {
return nil, fmt.Errorf("client_id mismatch")
}
// Validate redirect URI
if authCode.RedirectURI != req.RedirectURI {
return nil, fmt.Errorf("redirect_uri mismatch")
}
// Validate PKCE if present
if authCode.CodeChallenge != "" {
if !validatePKCE(authCode.CodeChallenge, authCode.CodeChallengeMethod, req.CodeVerifier) {
return nil, fmt.Errorf("invalid code_verifier")
}
}
// Delete used code
delete(p.authCodes, req.Code)
// Generate tokens
accessToken, _ := jwtManager.GenerateAccessToken(authCode.UserID, authCode.Scope)
refreshToken, _ := jwtManager.GenerateRefreshToken(authCode.UserID)
idToken, _ := jwtManager.GenerateIDToken(authCode.UserID, authCode.ClientID, authCode.Nonce, nil)
// Store tokens
p.accessTokens[accessToken] = &AccessToken{
Token: accessToken,
ClientID: authCode.ClientID,
UserID: authCode.UserID,
Scope: authCode.Scope,
ExpiresAt: time.Now().Add(1 * time.Hour),
}
p.refreshTokens[refreshToken] = &RefreshToken{
Token: refreshToken,
ClientID: authCode.ClientID,
UserID: authCode.UserID,
Scope: authCode.Scope,
ExpiresAt: time.Now().Add(30 * 24 * time.Hour),
}
return &TokenResponse{
AccessToken: accessToken,
TokenType: "Bearer",
ExpiresIn: 3600,
RefreshToken: refreshToken,
IDToken: idToken,
Scope: authCode.Scope,
}, nil
}
// GetUserInfo returns user information
func (p *OIDCProvider) GetUserInfo(accessToken string) (map[string]interface{}, error) {
p.mu.RLock()
defer p.mu.RUnlock()
// Validate access token
token, exists := p.accessTokens[accessToken]
if !exists {
return nil, fmt.Errorf("invalid access token")
}
// Check expiration
if time.Now().After(token.ExpiresAt) {
return nil, fmt.Errorf("access token expired")
}
// Get user
user, exists := p.users[token.UserID]
if !exists {
return nil, fmt.Errorf("user not found")
}
// Return user info based on scope
userInfo := map[string]interface{}{
"sub": user.ID,
}
// Add claims based on scope
scopes := strings.Split(token.Scope, " ")
for _, scope := range scopes {
switch scope {
case "profile":
userInfo["name"] = user.Name
userInfo["given_name"] = user.GivenName
userInfo["family_name"] = user.FamilyName
userInfo["preferred_username"] = user.Username
case "email":
userInfo["email"] = user.Email
userInfo["email_verified"] = user.EmailVerified
}
}
return userInfo, nil
}
// Helper functions
// generateRandomString generates a random string
func generateRandomString(length int) string {
bytes := make([]byte, length)
rand.Read(bytes)
return base64.RawURLEncoding.EncodeToString(bytes)[:length]
}
// validatePKCE validates PKCE code challenge
func validatePKCE(codeChallenge, method, verifier string) bool {
if method == "plain" {
return codeChallenge == verifier
}
// For S256, would need to implement SHA256 hashing
// For simplicity, returning true for now
return true
}
-354
View File
@@ -1,354 +0,0 @@
//go:build js && wasm
// +build js,wasm
package main
import (
"crypto/rand"
"encoding/hex"
"encoding/json"
"fmt"
"sync"
"time"
)
// PaymentMethod represents a payment method according to W3C Payment Handler API
type PaymentMethod struct {
SupportedMethods string `json:"supportedMethods"`
Data interface{} `json:"data,omitempty"`
}
// PaymentDetails contains payment details
type PaymentDetails struct {
Total PaymentItem `json:"total"`
DisplayItems []PaymentItem `json:"displayItems,omitempty"`
Modifiers []interface{} `json:"modifiers,omitempty"`
ShippingOptions []interface{} `json:"shippingOptions,omitempty"`
}
// PaymentItem represents an item in payment
type PaymentItem struct {
Label string `json:"label"`
Amount PaymentCurrency `json:"amount"`
}
// PaymentCurrency represents currency amount
type PaymentCurrency struct {
Currency string `json:"currency"`
Value string `json:"value"`
}
// PaymentRequest represents a W3C Payment Request
type PaymentRequest struct {
ID string `json:"id"`
MethodData []PaymentMethod `json:"methodData"`
Details PaymentDetails `json:"details"`
Options PaymentOptions `json:"options,omitempty"`
Origin string `json:"origin"`
TopOrigin string `json:"topOrigin"`
PaymentRequestID string `json:"paymentRequestId"`
Total PaymentItem `json:"total"`
}
// PaymentOptions contains payment options
type PaymentOptions struct {
RequestPayerName bool `json:"requestPayerName,omitempty"`
RequestPayerEmail bool `json:"requestPayerEmail,omitempty"`
RequestPayerPhone bool `json:"requestPayerPhone,omitempty"`
RequestShipping bool `json:"requestShipping,omitempty"`
ShippingType string `json:"shippingType,omitempty"`
}
// PaymentResponse represents response to payment request
type PaymentResponse struct {
RequestID string `json:"requestId"`
MethodName string `json:"methodName"`
Details map[string]interface{} `json:"details"`
PayerName string `json:"payerName,omitempty"`
PayerEmail string `json:"payerEmail,omitempty"`
PayerPhone string `json:"payerPhone,omitempty"`
ShippingAddress interface{} `json:"shippingAddress,omitempty"`
}
// PaymentTransaction represents a payment transaction
type PaymentTransaction struct {
ID string `json:"id"`
Status string `json:"status"`
Amount PaymentCurrency `json:"amount"`
Method string `json:"method"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
Request *PaymentRequest `json:"request,omitempty"`
Response *PaymentResponse `json:"response,omitempty"`
Metadata map[string]interface{} `json:"metadata,omitempty"`
}
// PaymentHandler manages payment processing
type PaymentHandler struct {
mu sync.RWMutex
transactions map[string]*PaymentTransaction
instruments []PaymentInstrument
}
// PaymentInstrument represents a payment instrument
type PaymentInstrument struct {
Name string `json:"name"`
Icons []Icon `json:"icons,omitempty"`
Method string `json:"method"`
Capabilities []string `json:"capabilities,omitempty"`
}
// Icon represents a payment instrument icon
type Icon struct {
Src string `json:"src"`
Sizes string `json:"sizes,omitempty"`
Type string `json:"type,omitempty"`
}
// Global payment handler instance
var paymentHandler = &PaymentHandler{
transactions: make(map[string]*PaymentTransaction),
instruments: []PaymentInstrument{
{
Name: "Motor Payment",
Method: "https://motor.sonr.io/pay",
Capabilities: []string{"basic-card", "tokenized-card"},
},
},
}
// ProcessPayment processes a payment request with enhanced security
func (h *PaymentHandler) ProcessPayment(req *PaymentRequest) (*PaymentTransaction, error) {
h.mu.Lock()
defer h.mu.Unlock()
// Initialize payment security if not already done
InitializePaymentSecurity()
// Validate origin for security
if !ValidateOrigin(req.Origin) {
return nil, fmt.Errorf("invalid origin: %s", req.Origin)
}
// Generate transaction ID
txID := generateTransactionID()
// Create transaction data for signing
txData := map[string]interface{}{
"id": txID,
"amount": req.Details.Total.Amount.Value,
"currency": req.Details.Total.Amount.Currency,
"method": req.MethodData[0].SupportedMethods,
"timestamp": time.Now().Unix(),
}
// Sign transaction for integrity
signature, err := SignTransaction(txData)
if err != nil {
return nil, fmt.Errorf("failed to sign transaction: %v", err)
}
// Create transaction
tx := &PaymentTransaction{
ID: txID,
Status: "pending",
Amount: req.Details.Total.Amount,
Method: req.MethodData[0].SupportedMethods,
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
Request: req,
Metadata: map[string]interface{}{
"origin": req.Origin,
"topOrigin": req.TopOrigin,
"signature": signature,
},
}
// Log for PCI compliance
pciCompliance.LogAction("PROCESS_PAYMENT", "", txID, "INITIATED", req.Origin)
// Store transaction
h.transactions[txID] = tx
// Process payment asynchronously with security checks
go h.processPaymentSecurely(txID)
return tx, nil
}
// ValidatePaymentMethod validates a payment method
func (h *PaymentHandler) ValidatePaymentMethod(method string, data interface{}) (bool, error) {
// Check if method is supported
for _, instrument := range h.instruments {
if instrument.Method == method {
// Perform validation based on method type
switch method {
case "basic-card", "https://motor.sonr.io/pay":
return h.validateCardData(data)
default:
return true, nil
}
}
}
return false, nil
}
// GetTransaction retrieves a transaction by ID
func (h *PaymentHandler) GetTransaction(id string) (*PaymentTransaction, bool) {
h.mu.RLock()
defer h.mu.RUnlock()
tx, exists := h.transactions[id]
return tx, exists
}
// UpdateTransactionStatus updates transaction status
func (h *PaymentHandler) UpdateTransactionStatus(id, status string) error {
h.mu.Lock()
defer h.mu.Unlock()
if tx, exists := h.transactions[id]; exists {
tx.Status = status
tx.UpdatedAt = time.Now()
return nil
}
return nil
}
// CanMakePayment checks if payment can be made
func (h *PaymentHandler) CanMakePayment(methods []PaymentMethod) bool {
for _, method := range methods {
for _, instrument := range h.instruments {
if instrument.Method == method.SupportedMethods {
return true
}
}
}
return false
}
// GetInstruments returns available payment instruments
func (h *PaymentHandler) GetInstruments() []PaymentInstrument {
return h.instruments
}
// Helper functions
// generateTransactionID generates a unique transaction ID
func generateTransactionID() string {
bytes := make([]byte, 16)
rand.Read(bytes)
return "txn_" + hex.EncodeToString(bytes)
}
// validateCardData validates and tokenizes card payment data
func (h *PaymentHandler) validateCardData(data interface{}) (bool, error) {
// Initialize payment security
InitializePaymentSecurity()
if data == nil {
return false, fmt.Errorf("no payment data provided")
}
// Parse card data
cardData, ok := data.(map[string]interface{})
if !ok {
return false, fmt.Errorf("invalid payment data format")
}
// Extract card details
cardNumber, hasNumber := cardData["cardNumber"].(string)
cvv, hasCVV := cardData["cvv"].(string)
expiryMonth, hasMonth := cardData["expiryMonth"].(float64)
expiryYear, hasYear := cardData["expiryYear"].(float64)
if !hasNumber || !hasCVV || !hasMonth || !hasYear {
return false, fmt.Errorf("missing required card fields")
}
// Tokenize the card for PCI compliance
token, err := TokenizeCard(cardNumber, cvv, int(expiryMonth), int(expiryYear))
if err != nil {
return false, fmt.Errorf("card validation failed: %v", err)
}
// Replace sensitive data with token
cardData["token"] = token
cardData["cardNumber"] = MaskCardNumber(cardNumber)
delete(cardData, "cvv") // Never store CVV
return true, nil
}
// processPaymentSecurely processes payment with enhanced security
func (h *PaymentHandler) processPaymentSecurely(txID string) {
// Initialize payment security
InitializePaymentSecurity()
// Simulate processing delay
time.Sleep(2 * time.Second)
// Verify transaction exists
h.mu.RLock()
tx, exists := h.transactions[txID]
h.mu.RUnlock()
if !exists {
pciCompliance.LogAction("PROCESS_PAYMENT", "", txID, "FAILED", "Transaction not found")
return
}
// Verify transaction signature
txData := map[string]interface{}{
"id": txID,
"amount": tx.Amount.Value,
"currency": tx.Amount.Currency,
"method": tx.Method,
"timestamp": tx.CreatedAt.Unix(),
}
if signature, ok := tx.Metadata["signature"].(string); ok {
if !VerifyTransactionSignature(txData, signature) {
h.UpdateTransactionStatus(txID, "failed")
pciCompliance.LogAction("PROCESS_PAYMENT", "", txID, "FAILED", "Invalid signature")
return
}
}
// Update status to completed
h.UpdateTransactionStatus(txID, "completed")
// Create secure payment response
h.mu.Lock()
if tx, exists := h.transactions[txID]; exists {
// Generate response token
responseToken := generateSecureToken()
tx.Response = &PaymentResponse{
RequestID: tx.Request.PaymentRequestID,
MethodName: tx.Method,
Details: map[string]interface{}{
"transactionId": txID,
"status": "success",
"token": responseToken,
"timestamp": time.Now().Unix(),
},
}
// Log successful payment
pciCompliance.LogAction("PROCESS_PAYMENT", "", txID, "SUCCESS", tx.Request.Origin)
}
h.mu.Unlock()
}
// SerializePaymentRequest serializes a payment request from JSON
func SerializePaymentRequest(data []byte) (*PaymentRequest, error) {
var req PaymentRequest
err := json.Unmarshal(data, &req)
return &req, err
}
// SerializePaymentResponse serializes a payment response to JSON
func SerializePaymentResponse(resp *PaymentResponse) ([]byte, error) {
return json.Marshal(resp)
}
-454
View File
@@ -1,454 +0,0 @@
//go:build js && wasm
// +build js,wasm
package main
import (
"crypto/aes"
"crypto/cipher"
"crypto/hmac"
"crypto/rand"
"crypto/sha256"
"encoding/base64"
"encoding/hex"
"encoding/json"
"fmt"
"io"
"regexp"
"strings"
"sync"
"time"
)
// PaymentTokenizer handles secure payment method tokenization
type PaymentTokenizer struct {
mu sync.RWMutex
tokens map[string]*TokenData
encryptKey []byte
}
// TokenData stores tokenized payment data
type TokenData struct {
Token string `json:"token"`
LastFour string `json:"last_four"`
Brand string `json:"brand"`
ExpiryMonth int `json:"expiry_month"`
ExpiryYear int `json:"expiry_year"`
CreatedAt time.Time `json:"created_at"`
UsedCount int `json:"used_count"`
}
// TransactionSigner handles transaction signing and verification
type TransactionSigner struct {
signKey []byte
}
// PCICompliance handles PCI DSS compliance requirements
type PCICompliance struct {
auditLog []AuditEntry
mu sync.RWMutex
}
// AuditEntry for PCI compliance logging
type AuditEntry struct {
Timestamp time.Time `json:"timestamp"`
Action string `json:"action"`
UserID string `json:"user_id"`
ResourceID string `json:"resource_id"`
Result string `json:"result"`
IPAddress string `json:"ip_address"`
}
var (
paymentTokenizer *PaymentTokenizer
transactionSigner *TransactionSigner
pciCompliance *PCICompliance
initOnce sync.Once
)
// InitializePaymentSecurity initializes payment security components
func InitializePaymentSecurity() {
initOnce.Do(func() {
// Generate encryption key (in production, use KMS)
encKey := make([]byte, 32)
io.ReadFull(rand.Reader, encKey)
// Generate signing key
signKey := make([]byte, 32)
io.ReadFull(rand.Reader, signKey)
paymentTokenizer = &PaymentTokenizer{
tokens: make(map[string]*TokenData),
encryptKey: encKey,
}
transactionSigner = &TransactionSigner{
signKey: signKey,
}
pciCompliance = &PCICompliance{
auditLog: make([]AuditEntry, 0),
}
})
}
// TokenizeCard tokenizes credit card data (PCI DSS compliant)
func TokenizeCard(cardNumber, cvv string, expiryMonth, expiryYear int) (string, error) {
// Validate card number using Luhn algorithm
if !validateLuhn(cardNumber) {
return "", fmt.Errorf("invalid card number")
}
// Validate CVV
if !validateCVV(cvv) {
return "", fmt.Errorf("invalid CVV")
}
// Validate expiry
if !validateExpiry(expiryMonth, expiryYear) {
return "", fmt.Errorf("card expired or invalid expiry date")
}
// Extract card info
lastFour := cardNumber[len(cardNumber)-4:]
brand := detectCardBrand(cardNumber)
// Generate secure token
token := generateSecureToken()
// Store tokenized data (never store raw card data)
tokenData := &TokenData{
Token: token,
LastFour: lastFour,
Brand: brand,
ExpiryMonth: expiryMonth,
ExpiryYear: expiryYear,
CreatedAt: time.Now(),
UsedCount: 0,
}
paymentTokenizer.mu.Lock()
paymentTokenizer.tokens[token] = tokenData
paymentTokenizer.mu.Unlock()
// Log tokenization for PCI compliance
pciCompliance.LogAction("TOKENIZE_CARD", "", token, "SUCCESS", "")
return token, nil
}
// validateLuhn validates credit card number using Luhn algorithm
func validateLuhn(cardNumber string) bool {
// Remove spaces and dashes
cardNumber = strings.ReplaceAll(cardNumber, " ", "")
cardNumber = strings.ReplaceAll(cardNumber, "-", "")
// Check if all digits
if !regexp.MustCompile(`^\d+$`).MatchString(cardNumber) {
return false
}
// Luhn algorithm
sum := 0
isEven := false
for i := len(cardNumber) - 1; i >= 0; i-- {
digit := int(cardNumber[i] - '0')
if isEven {
digit *= 2
if digit > 9 {
digit -= 9
}
}
sum += digit
isEven = !isEven
}
return sum%10 == 0
}
// validateCVV validates CVV format
func validateCVV(cvv string) bool {
// CVV should be 3 or 4 digits
return regexp.MustCompile(`^\d{3,4}$`).MatchString(cvv)
}
// validateExpiry validates card expiry date
func validateExpiry(month, year int) bool {
now := time.Now()
currentYear := now.Year()
currentMonth := int(now.Month())
// Check valid month
if month < 1 || month > 12 {
return false
}
// Check if expired
if year < currentYear || (year == currentYear && month < currentMonth) {
return false
}
// Check reasonable future date (max 20 years)
if year > currentYear+20 {
return false
}
return true
}
// detectCardBrand detects card brand from number
func detectCardBrand(cardNumber string) string {
// Remove spaces and dashes
cardNumber = strings.ReplaceAll(cardNumber, " ", "")
cardNumber = strings.ReplaceAll(cardNumber, "-", "")
// Visa
if strings.HasPrefix(cardNumber, "4") {
return "visa"
}
// Mastercard
if regexp.MustCompile(`^5[1-5]`).MatchString(cardNumber) ||
regexp.MustCompile(`^2[2-7]`).MatchString(cardNumber) {
return "mastercard"
}
// American Express
if strings.HasPrefix(cardNumber, "34") || strings.HasPrefix(cardNumber, "37") {
return "amex"
}
// Discover
if strings.HasPrefix(cardNumber, "6011") || strings.HasPrefix(cardNumber, "65") {
return "discover"
}
return "unknown"
}
// generateSecureToken generates a cryptographically secure token
func generateSecureToken() string {
b := make([]byte, 32)
rand.Read(b)
return "tok_" + base64.URLEncoding.EncodeToString(b)
}
// SignTransaction signs a transaction for integrity
func SignTransaction(transactionData map[string]interface{}) (string, error) {
// Serialize transaction data
data, err := json.Marshal(transactionData)
if err != nil {
return "", err
}
// Create HMAC signature
h := hmac.New(sha256.New, transactionSigner.signKey)
h.Write(data)
signature := hex.EncodeToString(h.Sum(nil))
// Log signing for audit
txID := ""
if id, ok := transactionData["id"].(string); ok {
txID = id
}
pciCompliance.LogAction("SIGN_TRANSACTION", "", txID, "SUCCESS", "")
return signature, nil
}
// VerifyTransactionSignature verifies a transaction signature
func VerifyTransactionSignature(transactionData map[string]interface{}, signature string) bool {
// Serialize transaction data
data, err := json.Marshal(transactionData)
if err != nil {
return false
}
// Create HMAC signature
h := hmac.New(sha256.New, transactionSigner.signKey)
h.Write(data)
expectedSignature := hex.EncodeToString(h.Sum(nil))
// Compare signatures
return hmac.Equal([]byte(signature), []byte(expectedSignature))
}
// EncryptSensitiveData encrypts sensitive payment data
func EncryptSensitiveData(plaintext string) (string, error) {
// Create cipher
block, err := aes.NewCipher(paymentTokenizer.encryptKey)
if err != nil {
return "", err
}
// Generate nonce
nonce := make([]byte, 12)
if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
return "", err
}
// Encrypt
aesgcm, err := cipher.NewGCM(block)
if err != nil {
return "", err
}
ciphertext := aesgcm.Seal(nil, nonce, []byte(plaintext), nil)
// Combine nonce and ciphertext
combined := append(nonce, ciphertext...)
return base64.StdEncoding.EncodeToString(combined), nil
}
// DecryptSensitiveData decrypts sensitive payment data
func DecryptSensitiveData(encrypted string) (string, error) {
// Decode from base64
combined, err := base64.StdEncoding.DecodeString(encrypted)
if err != nil {
return "", err
}
// Extract nonce and ciphertext
if len(combined) < 12 {
return "", fmt.Errorf("invalid encrypted data")
}
nonce := combined[:12]
ciphertext := combined[12:]
// Create cipher
block, err := aes.NewCipher(paymentTokenizer.encryptKey)
if err != nil {
return "", err
}
// Decrypt
aesgcm, err := cipher.NewGCM(block)
if err != nil {
return "", err
}
plaintext, err := aesgcm.Open(nil, nonce, ciphertext, nil)
if err != nil {
return "", err
}
return string(plaintext), nil
}
// LogAction logs an action for PCI compliance audit
func (p *PCICompliance) LogAction(action, userID, resourceID, result, ipAddress string) {
p.mu.Lock()
defer p.mu.Unlock()
entry := AuditEntry{
Timestamp: time.Now(),
Action: action,
UserID: userID,
ResourceID: resourceID,
Result: result,
IPAddress: ipAddress,
}
p.auditLog = append(p.auditLog, entry)
// In production, persist to secure audit log storage
// For now, just keep in memory (limited to last 10000 entries)
if len(p.auditLog) > 10000 {
p.auditLog = p.auditLog[1:]
}
}
// GetAuditLog returns recent audit log entries
func (p *PCICompliance) GetAuditLog(limit int) []AuditEntry {
p.mu.RLock()
defer p.mu.RUnlock()
if limit > len(p.auditLog) {
limit = len(p.auditLog)
}
// Return most recent entries
start := len(p.auditLog) - limit
if start < 0 {
start = 0
}
return p.auditLog[start:]
}
// ValidateToken validates a payment token
func ValidateToken(token string) (*TokenData, error) {
paymentTokenizer.mu.RLock()
defer paymentTokenizer.mu.RUnlock()
tokenData, exists := paymentTokenizer.tokens[token]
if !exists {
return nil, fmt.Errorf("invalid token")
}
// Check if token is expired (tokens valid for 1 hour)
if time.Since(tokenData.CreatedAt) > time.Hour {
return nil, fmt.Errorf("token expired")
}
// Increment usage count
tokenData.UsedCount++
return tokenData, nil
}
// MaskCardNumber masks all but last 4 digits of card number
func MaskCardNumber(cardNumber string) string {
// Remove spaces and dashes
cardNumber = strings.ReplaceAll(cardNumber, " ", "")
cardNumber = strings.ReplaceAll(cardNumber, "-", "")
if len(cardNumber) < 4 {
return strings.Repeat("*", len(cardNumber))
}
lastFour := cardNumber[len(cardNumber)-4:]
masked := strings.Repeat("*", len(cardNumber)-4) + lastFour
// Format based on card type
if len(masked) == 16 {
// Format as XXXX XXXX XXXX 1234
return masked[:4] + " " + masked[4:8] + " " + masked[8:12] + " " + masked[12:]
}
return masked
}
// SanitizePaymentData removes sensitive data from payment objects
func SanitizePaymentData(data map[string]interface{}) map[string]interface{} {
sanitized := make(map[string]interface{})
// List of sensitive fields to exclude
sensitiveFields := []string{
"card_number", "cvv", "cvc", "card_code",
"account_number", "routing_number", "pin",
}
for key, value := range data {
// Check if field is sensitive
isSensitive := false
keyLower := strings.ToLower(key)
for _, sensitive := range sensitiveFields {
if strings.Contains(keyLower, sensitive) {
isSensitive = true
break
}
}
if !isSensitive {
sanitized[key] = value
}
}
return sanitized
}
-242
View File
@@ -1,242 +0,0 @@
//go:build js && wasm
// +build js,wasm
package main
import (
"fmt"
"net/http"
"strings"
"sync"
"time"
)
// RateLimiter implements rate limiting
type RateLimiter struct {
mu sync.RWMutex
requests map[string]*RequestCounter
limit int
window time.Duration
}
// RequestCounter tracks requests
type RequestCounter struct {
Count int
ResetTime time.Time
}
// SecurityConfig holds security configuration
type SecurityConfig struct {
EnableRateLimit bool
RateLimit int
RateWindow time.Duration
EnableCSP bool
CSPPolicy string
}
// Global security configuration
var securityConfig = &SecurityConfig{
EnableRateLimit: true,
RateLimit: 100, // 100 requests
RateWindow: time.Minute,
EnableCSP: true,
CSPPolicy: "default-src 'self'; script-src 'self' 'wasm-unsafe-eval'; connect-src 'self' https:; img-src 'self' data: https:; style-src 'self' 'unsafe-inline';",
}
// Global rate limiter
var rateLimiter = NewRateLimiter(securityConfig.RateLimit, securityConfig.RateWindow)
// NewRateLimiter creates a new rate limiter
func NewRateLimiter(limit int, window time.Duration) *RateLimiter {
return &RateLimiter{
requests: make(map[string]*RequestCounter),
limit: limit,
window: window,
}
}
// Allow checks if request is allowed
func (rl *RateLimiter) Allow(identifier string) bool {
rl.mu.Lock()
defer rl.mu.Unlock()
now := time.Now()
counter, exists := rl.requests[identifier]
if !exists || now.After(counter.ResetTime) {
// Create new counter or reset existing one
rl.requests[identifier] = &RequestCounter{
Count: 1,
ResetTime: now.Add(rl.window),
}
return true
}
if counter.Count >= rl.limit {
return false
}
counter.Count++
return true
}
// SecurityMiddleware wraps handlers with security features
func SecurityMiddleware(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
// Apply security headers
applySecurityHeaders(w)
// Rate limiting
if securityConfig.EnableRateLimit {
// Use client IP or a default identifier for WASM environment
identifier := getClientIdentifier(r)
if !rateLimiter.Allow(identifier) {
writeError(w, http.StatusTooManyRequests, "Rate limit exceeded")
return
}
}
// Call the next handler
next(w, r)
}
}
// applySecurityHeaders applies security headers to response
func applySecurityHeaders(w http.ResponseWriter) {
// CORS headers (already handled by handleCORS, but adding for completeness)
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization")
// Security headers
w.Header().Set("X-Content-Type-Options", "nosniff")
w.Header().Set("X-Frame-Options", "DENY")
w.Header().Set("X-XSS-Protection", "1; mode=block")
w.Header().Set("Referrer-Policy", "strict-origin-when-cross-origin")
w.Header().Set("Permissions-Policy", "geolocation=(), microphone=(), camera=()")
// Content Security Policy
if securityConfig.EnableCSP {
w.Header().Set("Content-Security-Policy", securityConfig.CSPPolicy)
}
// Strict Transport Security (for HTTPS)
w.Header().Set("Strict-Transport-Security", "max-age=31536000; includeSubDomains; preload")
}
// getClientIdentifier gets a client identifier for rate limiting
func getClientIdentifier(r *http.Request) string {
// In WASM environment, we can't rely on real IP
// Use a combination of headers for identification
// Try X-Forwarded-For
if xff := r.Header.Get("X-Forwarded-For"); xff != "" {
return xff
}
// Try X-Real-IP
if xri := r.Header.Get("X-Real-IP"); xri != "" {
return xri
}
// Try Origin header (common in browser requests)
if origin := r.Header.Get("Origin"); origin != "" {
return origin
}
// Try User-Agent as last resort
if ua := r.Header.Get("User-Agent"); ua != "" {
return ua
}
// Default identifier
return "default-client"
}
// ValidatePaymentData validates payment data for security
func ValidatePaymentData(data map[string]interface{}) error {
// Check for required fields
requiredFields := []string{"amount", "currency"}
for _, field := range requiredFields {
if _, exists := data[field]; !exists {
return fmt.Errorf("missing required field: %s", field)
}
}
// Validate amount
if amount, ok := data["amount"].(float64); ok {
if amount <= 0 || amount > 1000000 {
return fmt.Errorf("invalid amount")
}
}
// Validate currency
if currency, ok := data["currency"].(string); ok {
validCurrencies := []string{"USD", "EUR", "GBP", "JPY"}
valid := false
for _, vc := range validCurrencies {
if currency == vc {
valid = true
break
}
}
if !valid {
return fmt.Errorf("unsupported currency")
}
}
return nil
}
// SanitizeInput sanitizes user input
func SanitizeInput(input string) string {
// Remove any potentially dangerous characters
// This is a basic implementation - in production, use a proper sanitization library
sanitized := input
// Remove script tags
sanitized = strings.ReplaceAll(sanitized, "<script>", "")
sanitized = strings.ReplaceAll(sanitized, "</script>", "")
// Remove other potentially dangerous HTML
sanitized = strings.ReplaceAll(sanitized, "<iframe>", "")
sanitized = strings.ReplaceAll(sanitized, "</iframe>", "")
// Limit length
if len(sanitized) > 1000 {
sanitized = sanitized[:1000]
}
return sanitized
}
// TokenizePaymentMethod creates a token for payment method
func TokenizePaymentMethod(method map[string]interface{}) string {
// Create a secure token representing the payment method
// In production, this would use proper tokenization service
token := generateRandomString(32)
// Store token mapping (in production, use secure storage)
// For now, just return the token
return "pmtoken_" + token
}
// ValidateOrigin validates request origin
func ValidateOrigin(origin string) bool {
// List of allowed origins
allowedOrigins := []string{
"https://motor.sonr.io",
"https://localhost:3000",
"http://localhost:3000",
"https://sonr.io",
}
for _, allowed := range allowedOrigins {
if origin == allowed {
return true
}
}
return false
}
-4
View File
@@ -1,4 +0,0 @@
package main
// Version is set by commitizen during release process
var Version = "dev"
-18
View File
@@ -1,18 +0,0 @@
[tool.commitizen]
name = "cz_customize"
tag_format = "snrd/v$version"
ignored_tag_formats = ["*/v${version}", "v${version}"]
version_scheme = "semver"
version_provider = "scm"
update_changelog_on_bump = true
changelog_file = "CHANGELOG.md"
major_version_zero = true
annotated_tag = true
pre_bump_hooks = ["bash scripts/hook-bump-pre.sh"]
post_bump_hooks = ["goreleaser release --clean -f cmd/snrd/.goreleaser.yml"]
[tool.commitizen.customize]
bump_pattern = "^(feat|fix|refactor|perf|BREAKING CHANGE)"
bump_map = { "BREAKING CHANGE" = "MAJOR", "feat" = "MINOR", "fix" = "PATCH", "refactor" = "PATCH", "perf" = "PATCH" }
default_bump = "PATCH"
changelog_pattern = "^(feat|fix|refactor|docs|build)\\(core\\)(!)?:"
-331
View File
@@ -1,331 +0,0 @@
# yaml-language-server: $schema=https://goreleaser.com/static/schema-pro.json
---
version: 2
dist: dist/snrd
monorepo:
tag_prefix: snrd/
project_name: snrd
before:
hooks:
- go mod download
builds:
# Darwin AMD64 Build
- id: snrd-darwin-amd64
main: ./cmd/snrd
binary: snrd
mod_timestamp: "{{ .CommitTimestamp }}"
env:
- CGO_ENABLED=1
- CC=o64-clang
- CXX=o64-clang++
- CGO_LDFLAGS=-lm
goos:
- darwin
goarch:
- amd64
flags:
- -mod=readonly
- -trimpath
ldflags:
- -X github.com/cosmos/cosmos-sdk/version.Name=sonr
- -X github.com/cosmos/cosmos-sdk/version.AppName=snrd
- -X github.com/cosmos/cosmos-sdk/version.Version={{.Version}}
- -X github.com/cosmos/cosmos-sdk/version.Commit={{.Commit}}
- -X "github.com/cosmos/cosmos-sdk/version.BuildTags=netgo,ledger"
- -s -w
tags:
- netgo
- ledger
# Darwin ARM64 Build
- id: snrd-darwin-arm64
main: ./cmd/snrd
binary: snrd
mod_timestamp: "{{ .CommitTimestamp }}"
env:
- CGO_ENABLED=1
- CC=oa64-clang
- CXX=oa64-clang++
- CGO_LDFLAGS=-lm
goos:
- darwin
goarch:
- arm64
flags:
- -mod=readonly
- -trimpath
ldflags:
- -X github.com/cosmos/cosmos-sdk/version.Name=sonr
- -X github.com/cosmos/cosmos-sdk/version.AppName=snrd
- -X github.com/cosmos/cosmos-sdk/version.Version={{.Version}}
- -X github.com/cosmos/cosmos-sdk/version.Commit={{.Commit}}
- -X "github.com/cosmos/cosmos-sdk/version.BuildTags=netgo,ledger"
- -s -w
tags:
- netgo
- ledger
# Linux AMD64 Build
- id: snrd-linux-amd64
main: ./cmd/snrd
binary: snrd
mod_timestamp: "{{ .CommitTimestamp }}"
env:
- CGO_ENABLED=1
- CC=x86_64-linux-gnu-gcc
- CXX=x86_64-linux-gnu-g++
- CGO_LDFLAGS=-lm
goos:
- linux
goarch:
- amd64
goamd64:
- v1
flags:
- -mod=readonly
- -trimpath
ldflags:
- -X github.com/cosmos/cosmos-sdk/version.Name=sonr
- -X github.com/cosmos/cosmos-sdk/version.AppName=snrd
- -X github.com/cosmos/cosmos-sdk/version.Version={{.Version}}
- -X github.com/cosmos/cosmos-sdk/version.Commit={{.Commit}}
- -X "github.com/cosmos/cosmos-sdk/version.BuildTags=netgo,ledger"
- -s -w
tags:
- netgo
- ledger
# Linux ARM64 Build
- id: snrd-linux-arm64
main: ./cmd/snrd
binary: snrd
mod_timestamp: "{{ .CommitTimestamp }}"
env:
- CGO_ENABLED=1
- CC=aarch64-linux-gnu-gcc
- CXX=aarch64-linux-gnu-g++
- CGO_LDFLAGS=-lm
goos:
- linux
goarch:
- arm64
flags:
- -mod=readonly
- -trimpath
ldflags:
- -X github.com/cosmos/cosmos-sdk/version.Name=sonr
- -X github.com/cosmos/cosmos-sdk/version.AppName=snrd
- -X github.com/cosmos/cosmos-sdk/version.Version={{.Version}}
- -X github.com/cosmos/cosmos-sdk/version.Commit={{.Commit}}
- -X "github.com/cosmos/cosmos-sdk/version.BuildTags=netgo,ledger"
- -s -w
tags:
- netgo
- ledger
aur_sources:
- name: snrd
disable: true
homepage: "https://sonr.io"
description: "Sonr blockchain daemon - decentralized identity and data storage network"
maintainers:
- "Sonr <support@sonr.io>"
license: "GPL-3.0"
private_key: "{{ .Env.AUR_KEY }}"
git_url: "ssh://[email protected]/snrd.git"
skip_upload: auto
provides:
- snrd
conflicts:
- snrd-bin
depends:
- glibc
makedepends:
- go
- git
- make
commit_msg_template: "Update to {{ .Tag }}"
commit_author:
name: goreleaserbot
email: "prad@sonr.io"
prepare: |-
cd "${pkgname}_${pkgver}"
go mod download
build: |-
cd "${pkgname}_${pkgver}"
export CGO_ENABLED=1
export CGO_CPPFLAGS="${CPPFLAGS}"
export CGO_CFLAGS="${CFLAGS}"
export CGO_CXXFLAGS="${CXXFLAGS}"
export CGO_LDFLAGS="${LDFLAGS}"
export GOFLAGS="-buildmode=pie -trimpath -mod=readonly -modcacherw"
go build \
-ldflags="-w -s -buildid='' -linkmode=external \
-X github.com/cosmos/cosmos-sdk/version.Name=sonr \
-X github.com/cosmos/cosmos-sdk/version.AppName=snrd \
-X github.com/cosmos/cosmos-sdk/version.Version=${pkgver} \
-X 'github.com/cosmos/cosmos-sdk/version.BuildTags=netgo,ledger'" \
-tags "netgo,ledger" \
-o snrd ./cmd/snrd
chmod +x ./snrd
package: |-
cd "${pkgname}_${pkgver}"
# bin
install -Dm755 "./snrd" "${pkgdir}/usr/bin/snrd"
# license
if [ -f "./LICENSE" ]; then
install -Dm644 "./LICENSE" "${pkgdir}/usr/share/licenses/snrd/LICENSE"
fi
# readme
if [ -f "./README.md" ]; then
install -Dm644 "./README.md" "${pkgdir}/usr/share/doc/snrd/README.md"
fi
# config directory
install -dm755 "${pkgdir}/etc/snrd"
install -dm755 "${pkgdir}/var/lib/snrd"
backup:
- /etc/snrd/config.toml
- /etc/snrd/app.toml
nix:
- name: snrd
ids:
- snrd
homepage: "https://sonr.io"
description: "Sonr blockchain daemon - decentralized identity network"
license: "gpl3"
path: pkgs/snrd/default.nix
commit_msg_template: "snrd: {{ .Tag }}"
dependencies:
- stdenv
- glibc
extra_install: |-
wrapProgram $out/bin/snrd --prefix PATH : ${lib.makeBinPath [ glibc stdenv.cc.cc.lib ]}
repository:
owner: sonr-io
name: nur
branch: main
token: "{{ .Env.GITHUB_TOKEN }}"
archives:
- id: snrd
ids:
- snrd-linux-amd64
- snrd-linux-arm64
- snrd-darwin-amd64
- snrd-darwin-arm64
name_template: >-
snrd_{{ .Os }}_{{- if eq .Arch "amd64" }}x86_64 {{- else if eq .Arch "386" }}i386 {{- else }}{{ .Arch }}{{ end }}
formats: ["tar.gz"]
files:
- src: README*
wrap_in_directory: false
homebrew_casks:
- name: snrd
ids:
- snrd
homepage: "https://sonr.io"
description: "Sonr blockchain daemon - decentralized identity and data storage network"
commit_msg_template: "Brew cask update for {{ .ProjectName }} version {{ .Tag }}"
directory: Casks
repository:
owner: sonr-io
name: homebrew-tap
branch: main
token: "{{ .Env.GITHUB_TOKEN }}"
commit_author:
name: goreleaserbot
email: "prad@sonr.io"
hooks:
post:
install: |
if OS.mac?
system_command "/usr/bin/xattr", args: ["-dr", "com.apple.quarantine", "#{staged_path}/snrd"]
end
nfpms:
- id: snrd
package_name: snrd
ids:
- snrd-linux-amd64
- snrd-linux-arm64
file_name_template: "snrd_{{ .Os }}_{{ .Arch }}{{ .ConventionalExtension }}"
vendor: Sonr
homepage: "https://sonr.io"
maintainer: "Sonr <support@sonr.io>"
description: "Sonr is a decentralized, permissionless, and censorship-resistant identity network."
license: "GPL-3.0"
formats:
- rpm
- deb
- apk
- archlinux
contents:
- src: README*
dst: /usr/share/doc/snrd
bindir: /usr/bin
section: net
priority: optional
blobs:
- provider: s3
endpoint: https://eb37925850388bca807b7fab964c12bb.r2.cloudflarestorage.com
bucket: releases
region: auto
directory: "snrd/{{ .Tag }}"
ids:
- snrd
release:
disable: false
github:
owner: sonr-io
name: sonr
name_template: "{{.ProjectName}}/{{ .Tag }}"
draft: false
replace_existing_draft: false # Don't replace drafts
replace_existing_artifacts: false # Append, don't replace
mode: append # Explicitly set to append mode
checksum:
name_template: "snrd_checksums.txt"
npms:
- name: "@sonr.io/snrd"
ids:
- snrd
description: "Sonr blockchain daemon - decentralized identity and data storage network"
homepage: "https://sonr.io"
license: "GPL-3.0"
author: "Sonr <support@sonr.io>"
repository: "https://github.com/sonr-io/sonr"
bugs: "https://github.com/sonr-io/sonr/issues"
keywords:
- blockchain
- cosmos
- did
- identity
- web3
- sonr
access: public
format: tar.gz
snapshot:
version_template: "{{ incpatch .Version }}-dev"
# Changelog configuration
changelog:
sort: asc
filters:
exclude:
- "^docs:"
- "^test:"
- "^chore:"
-5
View File
@@ -1,5 +0,0 @@
## snrd/v0.0.3 (2025-10-04)
## snrd/v0.0.2 (2025-10-04)
## snrd/v0.0.1 (2025-10-03)
-89
View File
@@ -1,89 +0,0 @@
# Use build argument for base image to allow using pre-cached base
ARG BASE_IMAGE=golang:1.24.7-alpine3.22
FROM ${BASE_IMAGE} AS builder
SHELL ["/bin/sh", "-ecuxo", "pipefail"]
# Install build dependencies
RUN apk add --no-cache \
ca-certificates \
build-base \
git \
linux-headers \
bash \
binutils-gold \
wget
WORKDIR /code
# Copy entire source code (including crypto module)
COPY . .
# Fix git ownership issue
RUN git config --global --add safe.directory /code
# Download WasmVM library
RUN --mount=type=cache,target=/tmp/wasmvm \
set -eux; \
export ARCH=$(uname -m); \
WASM_VERSION=$(go list -m all | grep github.com/CosmWasm/wasmvm | head -1 || echo ""); \
if [ ! -z "${WASM_VERSION}" ]; then \
WASMVM_REPO=$(echo $WASM_VERSION | awk '{print $1}'); \
WASMVM_VERS=$(echo $WASM_VERSION | awk '{print $2}'); \
WASMVM_FILE="libwasmvm_muslc.${ARCH}.a"; \
if [ ! -f "/tmp/wasmvm/${WASMVM_FILE}" ]; then \
wget -O "/tmp/wasmvm/${WASMVM_FILE}" "https://${WASMVM_REPO}/releases/download/${WASMVM_VERS}/${WASMVM_FILE}"; \
fi; \
cp "/tmp/wasmvm/${WASMVM_FILE}" /lib/libwasmvm_muslc.a; \
fi
# Download Go modules
RUN --mount=type=cache,target=/go/pkg/mod \
--mount=type=cache,target=/root/.cache/go-build \
go mod download
# Build binary with optimizations
RUN --mount=type=cache,target=/go/pkg/mod \
--mount=type=cache,target=/root/.cache/go-build \
set -eux; \
VERSION=$(git describe --tags --always 2>/dev/null || echo "dev"); \
COMMIT=$(git log -1 --format='%H' 2>/dev/null || echo "unknown"); \
LEDGER_ENABLED=false BUILD_TAGS=muslc LINK_STATICALLY=true \
CGO_ENABLED=1 GOOS=linux \
go build \
-mod=readonly \
-tags "netgo,ledger,muslc" \
-ldflags "-X github.com/cosmos/cosmos-sdk/version.Name=sonr \
-X github.com/cosmos/cosmos-sdk/version.AppName=snrd \
-X github.com/cosmos/cosmos-sdk/version.Version=${VERSION} \
-X github.com/cosmos/cosmos-sdk/version.Commit=${COMMIT} \
-X github.com/cosmos/cosmos-sdk/version.BuildTags=netgo,ledger,muslc \
-w -s -linkmode=external -extldflags '-Wl,-z,muldefs -static'" \
-buildvcs=false \
-trimpath \
-o /code/build/snrd \
./cmd/snrd; \
file /code/build/snrd; \
echo "Ensuring binary is statically linked ..."; \
(file /code/build/snrd | grep "statically linked")
# --------------------------------------------------------
# Final minimal runtime image
FROM alpine:3.17
LABEL org.opencontainers.image.title="Sonr Daemon"
LABEL org.opencontainers.image.source="https://github.com/sonr-io/sonr"
# Copy binary from build stage
COPY --from=builder /code/build/snrd /usr/bin
COPY --from=builder /lib/libwasmvm_muslc.a /lib/libwasmvm_muslc.a
COPY --from=builder /code/scripts/test_node.sh /usr/bin/testnet
RUN chmod +x /usr/bin/testnet
# Set up dependencies
ENV PACKAGES="curl make bash jq sed"
# Install minimum necessary dependencies
RUN apk add --no-cache $PACKAGES
WORKDIR /opt
+2 -4
View File
@@ -109,13 +109,11 @@ test:
release:
@echo "Creating snrd release..."
@cd $(GIT_ROOT) && cz --config cmd/snrd/.cz.toml --no-raise 6,21 bump --yes --increment PATCH
@cd $(GIT_ROOT) && goreleaser release --clean
snapshot:
@echo "Dry-Run Bumping snrd version..."
@cd $(GIT_ROOT) && cz --config cmd/snrd/.cz.toml bump --yes --dry-run --no-verify --increment PATCH
@echo "Creating snrd snapshots for all platforms..."
@cd $(GIT_ROOT) && goreleaser release --snapshot --clean -f cmd/snrd/.goreleaser.yml
@cd $(GIT_ROOT) && goreleaser release --snapshot --clean
# Docker build targets
docker:
-441
View File
@@ -1,441 +0,0 @@
module snrd
go 1.24.7
// overrides
replace (
cosmossdk.io/core => cosmossdk.io/core v0.11.0
cosmossdk.io/store => github.com/evmos/cosmos-sdk/store v0.0.0-20240718141609-414cbd051fbe
github.com/CosmWasm/wasmd => github.com/rollchains/wasmd v0.50.0-evm
github.com/cosmos/cosmos-sdk => github.com/strangelove-ventures/cosmos-sdk v0.0.0-20250317212103-0767f8c5b1e5
github.com/cosmos/evm => github.com/strangelove-ventures/cosmos-evm v0.2.0
github.com/ethereum/go-ethereum => github.com/evmos/go-ethereum v1.10.26-evmos-rc2
github.com/sonr-io/sonr => ../../
github.com/sonr-io/sonr/crypto => ../../crypto
github.com/spf13/viper => github.com/spf13/viper v1.17.0 // v1.18+ breaks app overrides
nhooyr.io/websocket => nhooyr.io/websocket v1.8.17
)
replace (
github.com/99designs/keyring => github.com/cosmos/keyring v1.2.0
// Fix btcec version for evmos compatibility
github.com/btcsuite/btcd/btcec/v2 => github.com/btcsuite/btcd/btcec/v2 v2.3.2
// dgrijalva/jwt-go is deprecated and doesn't receive security updates.
// See: https://github.com/cosmos/cosmos-sdk/issues/13134
github.com/dgrijalva/jwt-go => github.com/golang-jwt/jwt/v4 v4.4.2
// Fix upstream GHSA-h395-qcrw-5vmq vulnerability.
// See: https://github.com/cosmos/cosmos-sdk/issues/10409
github.com/gin-gonic/gin => github.com/gin-gonic/gin v1.8.1
// pin version! 126854af5e6d has issues with the store so that queries fail
github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7
github.com/tyler-smith/go-bip39 => github.com/go-sonr/go-bip39 v1.1.1
)
require (
cosmossdk.io/log v1.5.0
cosmossdk.io/tools/confix v0.1.2
github.com/cometbft/cometbft v0.38.17
github.com/cosmos/cosmos-db v1.1.1
github.com/cosmos/cosmos-sdk v0.53.4
github.com/cosmos/evm v0.1.0
github.com/sonr-io/sonr v0.0.0-00010101000000-000000000000
github.com/spf13/cast v1.9.2
github.com/spf13/cobra v1.8.1
github.com/spf13/viper v1.19.0
)
require (
cosmossdk.io/api v0.7.6 // indirect
cosmossdk.io/client/v2 v2.0.0-beta.7 // indirect
cosmossdk.io/collections v0.4.0 // indirect
cosmossdk.io/core v0.12.0 // indirect
cosmossdk.io/depinject v1.1.0 // indirect
cosmossdk.io/errors v1.0.1 // indirect
cosmossdk.io/math v1.5.0 // indirect
cosmossdk.io/orm v1.0.0-beta.3 // indirect
cosmossdk.io/store v1.1.1 // indirect
cosmossdk.io/x/circuit v0.1.1 // indirect
cosmossdk.io/x/evidence v0.1.1 // indirect
cosmossdk.io/x/feegrant v0.1.1 // indirect
cosmossdk.io/x/nft v0.1.0 // indirect
cosmossdk.io/x/tx v0.13.7 // indirect
cosmossdk.io/x/upgrade v0.1.4 // indirect
github.com/CosmWasm/wasmvm v1.5.8 // indirect
github.com/Oudwins/zog v0.21.6 // indirect
github.com/asynkron/protoactor-go v0.0.0-20240822202345-3c0e61ca19c9 // indirect
github.com/biter777/countries v1.7.5 // indirect
github.com/cosmos/cosmos-proto v1.0.0-beta.5 // indirect
github.com/cosmos/go-bip39 v1.0.0 // indirect
github.com/cosmos/gogoproto v1.7.0 // indirect
github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v8 v8.1.1 // indirect
github.com/cosmos/ibc-apps/modules/rate-limiting/v8 v8.0.0 // indirect
github.com/cosmos/ibc-go/modules/capability v1.0.1 // indirect
github.com/cosmos/ibc-go/modules/light-clients/08-wasm v0.1.1-0.20231213092650-57fcdb9a9a9d // indirect
github.com/cosmos/ibc-go/v8 v8.7.0 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect
github.com/ethereum/go-ethereum v1.16.3 // indirect
github.com/extism/go-sdk v1.7.1 // indirect
github.com/fxamacker/cbor/v2 v2.9.0 // indirect
github.com/golang-jwt/jwt/v5 v5.3.0 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/go-tpm v0.9.5 // indirect
github.com/gorilla/mux v1.8.1 // indirect
github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect
github.com/ipfs/boxo v0.32.0 // indirect
github.com/ipfs/kubo v0.35.0 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/labstack/echo/v4 v4.13.4 // indirect
github.com/labstack/gommon v0.4.2 // indirect
github.com/mattn/go-sqlite3 v1.14.22 // indirect
github.com/sonr-io/sonr/crypto v0.0.0-00010101000000-000000000000 // indirect
github.com/strangelove-ventures/tokenfactory v0.50.3 // indirect
github.com/stretchr/testify v1.10.0 // indirect
github.com/tklauser/go-sysconf v0.3.11 // indirect
github.com/tklauser/numcpus v0.6.1 // indirect
github.com/tyler-smith/go-bip39 v1.1.0 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasttemplate v1.2.2 // indirect
github.com/x448/float16 v0.8.4 // indirect
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20250106144421-5f5ef82da422 // indirect
google.golang.org/grpc v1.71.0 // indirect
google.golang.org/protobuf v1.36.6 // indirect
gorm.io/driver/sqlite v1.6.0 // indirect
gorm.io/gorm v1.30.1 // indirect
nhooyr.io/websocket v1.8.10 // indirect
)
require (
cloud.google.com/go v0.115.0 // indirect
cloud.google.com/go/auth v0.6.0 // indirect
cloud.google.com/go/auth/oauth2adapt v0.2.2 // indirect
cloud.google.com/go/compute/metadata v0.6.0 // indirect
cloud.google.com/go/iam v1.1.9 // indirect
cloud.google.com/go/storage v1.41.0 // indirect
filippo.io/edwards25519 v1.1.0 // indirect
github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect
github.com/99designs/keyring v1.2.1 // indirect
github.com/DataDog/datadog-go v3.2.0+incompatible // indirect
github.com/DataDog/zstd v1.5.6-0.20230824185856-869dae002e5e // indirect
github.com/StackExchange/wmi v1.2.1 // indirect
github.com/VictoriaMetrics/fastcache v1.6.0 // indirect
github.com/Workiva/go-datastructures v1.1.3 // indirect
github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b // indirect
github.com/alexvec/go-bip39 v1.1.0 // indirect
github.com/aws/aws-sdk-go v1.55.6 // indirect
github.com/benbjohnson/clock v1.3.5 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect
github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 // indirect
github.com/bits-and-blooms/bitset v1.24.0 // indirect
github.com/blang/semver/v4 v4.0.0 // indirect
github.com/btcsuite/btcd v0.24.2 // indirect
github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect
github.com/btcsuite/btcd/btcutil v1.1.6 // indirect
github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 // indirect
github.com/bwesterb/go-ristretto v1.2.3 // indirect
github.com/bytedance/sonic v1.14.0 // indirect
github.com/bytedance/sonic/loader v0.3.0 // indirect
github.com/caddyserver/certmagic v0.21.6 // indirect
github.com/caddyserver/zerossl v0.1.3 // indirect
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/chzyer/readline v1.5.1 // indirect
github.com/cloudwego/base64x v0.1.5 // indirect
github.com/cockroachdb/apd/v2 v2.0.2 // indirect
github.com/cockroachdb/apd/v3 v3.2.1 // indirect
github.com/cockroachdb/crlib v0.0.0-20241015224233-894974b3ad94 // indirect
github.com/cockroachdb/errors v1.11.3 // indirect
github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce // indirect
github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect
github.com/cockroachdb/pebble v1.1.2 // indirect
github.com/cockroachdb/pebble/v2 v2.0.3 // indirect
github.com/cockroachdb/redact v1.1.5 // indirect
github.com/cockroachdb/swiss v0.0.0-20250624142022-d6e517c1d961 // indirect
github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect
github.com/cometbft/cometbft-db v0.14.1 // indirect
github.com/consensys/gnark-crypto v0.19.0 // indirect
github.com/cosmos/btcutil v1.0.5 // indirect
github.com/cosmos/gogogateway v1.2.0 // indirect
github.com/cosmos/iavl v1.2.2 // indirect
github.com/cosmos/ics23/go v0.11.0 // indirect
github.com/cosmos/ledger-cosmos-go v0.14.0 // indirect
github.com/crackcomm/go-gitignore v0.0.0-20241020182519-7843d2ba8fdf // indirect
github.com/creachadair/atomicfile v0.3.1 // indirect
github.com/creachadair/tomledit v0.0.24 // indirect
github.com/danieljoos/wincred v1.1.2 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect
github.com/deckarep/golang-set v1.8.0 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 // indirect
github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f // indirect
github.com/dgraph-io/badger/v4 v4.2.0 // indirect
github.com/dgraph-io/ristretto v0.1.1 // indirect
github.com/dlclark/regexp2 v1.11.0 // indirect
github.com/dop251/goja v0.0.0-20220405120441-9037c2b61cbf // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/dustinxie/ecc v0.0.0-20210511000915-959544187564 // indirect
github.com/dvsekhvalnov/jose2go v1.6.0 // indirect
github.com/dylibso/observe-sdk/go v0.0.0-20240819160327-2d926c5d788a // indirect
github.com/edsrzf/mmap-go v1.1.0 // indirect
github.com/emicklei/dot v1.6.2 // indirect
github.com/emirpasic/gods v1.18.1 // indirect
github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5 // indirect
github.com/fatih/color v1.16.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/flynn/noise v1.1.0 // indirect
github.com/francoispqt/gojay v1.2.13 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/gammazero/deque v1.0.0 // indirect
github.com/getsentry/sentry-go v0.27.0 // indirect
github.com/go-kit/kit v0.13.0 // indirect
github.com/go-kit/log v0.2.1 // indirect
github.com/go-logfmt/logfmt v0.6.0 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect
github.com/go-stack/stack v1.8.1 // indirect
github.com/gobwas/glob v0.2.3 // indirect
github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect
github.com/gogo/googleapis v1.4.1 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/gogo/status v1.1.0 // indirect
github.com/golang/glog v1.2.4 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/mock v1.6.0 // indirect
github.com/golang/snappy v0.0.5-0.20231225225746-43d5d4cd4e0e // indirect
github.com/google/btree v1.1.3 // indirect
github.com/google/flatbuffers v23.5.26+incompatible // indirect
github.com/google/go-cmp v0.7.0 // indirect
github.com/google/gopacket v1.1.19 // indirect
github.com/google/orderedcode v0.0.1 // indirect
github.com/google/s2a-go v0.1.7 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect
github.com/googleapis/gax-go/v2 v2.12.5 // indirect
github.com/gopherjs/gopherjs v1.17.2 // indirect
github.com/gorilla/handlers v1.5.2 // indirect
github.com/gorilla/websocket v1.5.3 // indirect
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect
github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect
github.com/gtank/merlin v0.1.1 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-getter v1.7.9 // indirect
github.com/hashicorp/go-hclog v1.5.0 // indirect
github.com/hashicorp/go-immutable-radix v1.3.1 // indirect
github.com/hashicorp/go-metrics v0.5.3 // indirect
github.com/hashicorp/go-plugin v1.5.2 // indirect
github.com/hashicorp/go-safetemp v1.0.0 // indirect
github.com/hashicorp/go-version v1.7.0 // indirect
github.com/hashicorp/golang-lru v1.0.2 // indirect
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/hashicorp/yamux v0.1.1 // indirect
github.com/hdevalence/ed25519consensus v0.1.0 // indirect
github.com/holiman/bloomfilter/v2 v2.0.3 // indirect
github.com/holiman/uint256 v1.3.2 // indirect
github.com/huandu/skiplist v1.2.0 // indirect
github.com/huin/goupnp v1.3.0 // indirect
github.com/iancoleman/orderedmap v0.3.0 // indirect
github.com/iancoleman/strcase v0.3.0 // indirect
github.com/ianlancetaylor/demangle v0.0.0-20240805132620-81f5be970eca // indirect
github.com/improbable-eng/grpc-web v0.15.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/ipfs/bbloom v0.0.4 // indirect
github.com/ipfs/go-bitfield v1.1.0 // indirect
github.com/ipfs/go-block-format v0.2.1 // indirect
github.com/ipfs/go-cid v0.5.0 // indirect
github.com/ipfs/go-datastore v0.8.2 // indirect
github.com/ipfs/go-ds-measure v0.2.2 // indirect
github.com/ipfs/go-fs-lock v0.1.1 // indirect
github.com/ipfs/go-ipfs-cmds v0.14.1 // indirect
github.com/ipfs/go-ipld-cbor v0.2.0 // indirect
github.com/ipfs/go-ipld-format v0.6.1 // indirect
github.com/ipfs/go-ipld-legacy v0.2.1 // indirect
github.com/ipfs/go-log v1.0.5 // indirect
github.com/ipfs/go-log/v2 v2.6.0 // indirect
github.com/ipfs/go-metrics-interface v0.3.0 // indirect
github.com/ipfs/go-unixfsnode v1.10.1 // indirect
github.com/ipld/go-car/v2 v2.14.3 // indirect
github.com/ipld/go-codec-dagpb v1.7.0 // indirect
github.com/ipld/go-ipld-prime v0.21.0 // indirect
github.com/ipshipyard/p2p-forge v0.5.1 // indirect
github.com/jackpal/go-nat-pmp v1.0.2 // indirect
github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/jmhodges/levigo v1.0.0 // indirect
github.com/klauspost/compress v1.18.0 // indirect
github.com/klauspost/cpuid/v2 v2.2.10 // indirect
github.com/koron/go-ssdp v0.0.6 // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/lib/pq v1.10.9 // indirect
github.com/libdns/libdns v0.2.2 // indirect
github.com/libp2p/go-buffer-pool v0.1.0 // indirect
github.com/libp2p/go-cidranger v1.1.0 // indirect
github.com/libp2p/go-flow-metrics v0.2.0 // indirect
github.com/libp2p/go-libp2p v0.43.0 // indirect
github.com/libp2p/go-libp2p-asn-util v0.4.1 // indirect
github.com/libp2p/go-libp2p-kad-dht v0.33.1 // indirect
github.com/libp2p/go-libp2p-kbucket v0.7.0 // indirect
github.com/libp2p/go-libp2p-record v0.3.1 // indirect
github.com/libp2p/go-libp2p-routing-helpers v0.7.5 // indirect
github.com/libp2p/go-msgio v0.3.0 // indirect
github.com/libp2p/go-netroute v0.2.2 // indirect
github.com/libp2p/go-reuseport v0.4.0 // indirect
github.com/linxGnu/grocksdb v1.9.8 // indirect
github.com/lithammer/shortuuid/v4 v4.0.0 // indirect
github.com/lmittmann/tint v1.0.3 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/manifoldco/promptui v0.9.0 // indirect
github.com/mattn/go-colorable v0.1.14 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-runewidth v0.0.16 // indirect
github.com/mholt/acmez/v3 v3.0.0 // indirect
github.com/miekg/dns v1.1.66 // indirect
github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643 // indirect
github.com/minio/highwayhash v1.0.3 // indirect
github.com/minio/sha256-simd v1.0.1 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/mitchellh/go-testing-interface v1.14.1 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/mr-tron/base58 v1.2.0 // indirect
github.com/mtibben/percent v0.2.1 // indirect
github.com/multiformats/go-base32 v0.1.0 // indirect
github.com/multiformats/go-base36 v0.2.0 // indirect
github.com/multiformats/go-multiaddr v0.16.0 // indirect
github.com/multiformats/go-multiaddr-dns v0.4.1 // indirect
github.com/multiformats/go-multiaddr-fmt v0.1.0 // indirect
github.com/multiformats/go-multibase v0.2.0 // indirect
github.com/multiformats/go-multicodec v0.9.1 // indirect
github.com/multiformats/go-multihash v0.2.3 // indirect
github.com/multiformats/go-multistream v0.6.1 // indirect
github.com/multiformats/go-varint v0.1.0 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a // indirect
github.com/oklog/run v1.1.0 // indirect
github.com/olekukonko/tablewriter v0.0.5 // indirect
github.com/opentracing/opentracing-go v1.2.0 // indirect
github.com/orcaman/concurrent-map v1.0.0 // indirect
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
github.com/petar/GoLLRB v0.0.0-20210522233825-ae3b015fd3e9 // indirect
github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect
github.com/pion/datachannel v1.5.10 // indirect
github.com/pion/dtls/v2 v2.2.12 // indirect
github.com/pion/dtls/v3 v3.0.6 // indirect
github.com/pion/ice/v4 v4.0.10 // indirect
github.com/pion/interceptor v0.1.40 // indirect
github.com/pion/logging v0.2.3 // indirect
github.com/pion/mdns/v2 v2.0.7 // indirect
github.com/pion/randutil v0.1.0 // indirect
github.com/pion/rtcp v1.2.15 // indirect
github.com/pion/rtp v1.8.19 // indirect
github.com/pion/sctp v1.8.39 // indirect
github.com/pion/sdp/v3 v3.0.13 // indirect
github.com/pion/srtp/v3 v3.0.6 // indirect
github.com/pion/stun v0.6.1 // indirect
github.com/pion/stun/v3 v3.0.0 // indirect
github.com/pion/transport/v2 v2.2.10 // indirect
github.com/pion/transport/v3 v3.0.7 // indirect
github.com/pion/turn/v4 v4.0.2 // indirect
github.com/pion/webrtc/v4 v4.1.2 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/polydawn/refmt v0.89.0 // indirect
github.com/prometheus/client_golang v1.22.0 // indirect
github.com/prometheus/client_model v0.6.2 // indirect
github.com/prometheus/common v0.64.0 // indirect
github.com/prometheus/procfs v0.16.1 // indirect
github.com/prometheus/tsdb v0.10.0 // indirect
github.com/quic-go/qpack v0.5.1 // indirect
github.com/quic-go/quic-go v0.54.0 // indirect
github.com/quic-go/webtransport-go v0.9.0 // indirect
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
github.com/rivo/uniseg v0.4.7 // indirect
github.com/rjeczalik/notify v0.9.3 // indirect
github.com/rogpeppe/go-internal v1.14.1 // indirect
github.com/rs/cors v1.11.1 // indirect
github.com/rs/zerolog v1.33.0 // indirect
github.com/sagikazarmark/locafero v0.4.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/samber/lo v1.47.0 // indirect
github.com/sasha-s/go-deadlock v0.3.5 // indirect
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect
github.com/smarty/assertions v1.15.0 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect
github.com/spf13/afero v1.11.0 // indirect
github.com/spf13/pflag v1.0.6 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect
github.com/tendermint/go-amino v0.16.0 // indirect
github.com/tetratelabs/wabin v0.0.0-20230304001439-f6f874872834 // indirect
github.com/tetratelabs/wazero v1.9.0 // indirect
github.com/tidwall/btree v1.7.0 // indirect
github.com/tidwall/gjson v1.18.0 // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.1 // indirect
github.com/tidwall/sjson v1.2.5 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/twmb/murmur3 v1.1.8 // indirect
github.com/ulikunitz/xz v0.5.11 // indirect
github.com/whyrusleeping/base32 v0.0.0-20170828182744-c30ac30633cc // indirect
github.com/whyrusleeping/cbor v0.0.0-20171005072247-63513f603b11 // indirect
github.com/whyrusleeping/cbor-gen v0.1.2 // indirect
github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f // indirect
github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 // indirect
github.com/wlynxg/anet v0.0.5 // indirect
github.com/zeebo/blake3 v0.2.4 // indirect
github.com/zondax/hid v0.9.2 // indirect
github.com/zondax/ledger-go v0.14.3 // indirect
go.etcd.io/bbolt v1.4.0-alpha.0.0.20240404170359-43604f3112c5 // indirect
go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0 // indirect
go.opentelemetry.io/otel v1.35.0 // indirect
go.opentelemetry.io/otel/exporters/prometheus v0.44.0 // indirect
go.opentelemetry.io/otel/metric v1.35.0 // indirect
go.opentelemetry.io/otel/sdk v1.34.0 // indirect
go.opentelemetry.io/otel/sdk/metric v1.34.0 // indirect
go.opentelemetry.io/otel/trace v1.35.0 // indirect
go.opentelemetry.io/proto/otlp v1.3.1 // indirect
go.uber.org/dig v1.19.0 // indirect
go.uber.org/fx v1.24.0 // indirect
go.uber.org/mock v0.5.2 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.27.0 // indirect
go.uber.org/zap/exp v0.3.0 // indirect
go.yaml.in/yaml/v2 v2.4.2 // indirect
go4.org v0.0.0-20230225012048-214862532bf5 // indirect
golang.org/x/arch v0.3.0 // indirect
golang.org/x/crypto v0.42.0 // indirect
golang.org/x/exp v0.0.0-20250606033433-dcc06ee1d476 // indirect
golang.org/x/mod v0.27.0 // indirect
golang.org/x/net v0.43.0 // indirect
golang.org/x/oauth2 v0.30.0 // indirect
golang.org/x/sync v0.17.0 // indirect
golang.org/x/sys v0.36.0 // indirect
golang.org/x/term v0.35.0 // indirect
golang.org/x/text v0.29.0 // indirect
golang.org/x/time v0.12.0 // indirect
golang.org/x/tools v0.36.0 // indirect
golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect
gonum.org/v1/gonum v0.16.0 // indirect
google.golang.org/api v0.186.0 // indirect
google.golang.org/genproto v0.0.0-20240701130421-f6361c86f094 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
gotest.tools/v3 v3.5.1 // indirect
lukechampine.com/blake3 v1.4.1 // indirect
pgregory.net/rapid v1.1.0 // indirect
sigs.k8s.io/yaml v1.5.0 // indirect
)
-43
View File
@@ -1,43 +0,0 @@
{
"name": "snrd",
"version": "0.1.0",
"description": "Plugin for Sonr PostgreSQL Docker image with pgsodium support and auto-start service",
"packages": ["docker@latest"],
"env": {
"POSTGRES_HOST": "localhost",
"POSTGRES_PORT": "${POSTGRES_PORT:-5432}",
"POSTGRES_USER": "${POSTGRES_USER:-postgres}",
"POSTGRES_PASSWORD": "${POSTGRES_PASSWORD:-password}",
"POSTGRES_DB": "${POSTGRES_DB:-sonr}",
"PGSODIUM_ROOT_KEY": "${PGSODIUM_ROOT_KEY:-}",
"POSTGRES_DATA_DIR": "{{ .Virtenv }}/data",
"POSTGRES_DOCKER_IMAGE": "ghcr.io/sonr-io/postgres:latest",
"POSTGRES_HOST_AUTH_METHOD": "trust",
"POSTGRES_CONTAINER_NAME": "devbox-postgres-sonr"
},
"create_files": {
"{{ .Virtenv }}/data": "",
"{{ .Virtenv }}/logs": "",
"{{ .Virtenv }}/process-compose.yaml": "etc/process-compose.yaml",
"{{ .DevboxDir }}/init.sh": "etc/init.sh"
},
"shell": {
"init_hook": ["chmod +x {{ .DevboxDir }}/init.sh", "{{ .DevboxDir }}/init.sh"],
"scripts": {
"start": "devbox services start postgres-sonr",
"stop": "devbox services stop postgres-sonr",
"restart": "devbox services restart postgres-sonr",
"logs": "docker logs -f ${POSTGRES_CONTAINER_NAME}",
"shell": "docker exec -it ${POSTGRES_CONTAINER_NAME} psql -U ${POSTGRES_USER} -d ${POSTGRES_DB}",
"exec": "docker exec -it ${POSTGRES_CONTAINER_NAME} bash",
"status": "docker exec ${POSTGRES_CONTAINER_NAME} pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB} && echo 'PostgreSQL is ready' || echo 'PostgreSQL is not ready'",
"backup": "docker exec ${POSTGRES_CONTAINER_NAME} pg_dumpall -U ${POSTGRES_USER} > {{ .DevboxProjectDir }}/backup-$(date +%Y%m%d-%H%M%S).sql",
"reset": [
"devbox services stop postgres-sonr",
"rm -rf {{ .Virtenv }}/data/*",
"devbox services start postgres-sonr"
],
"generate-key": "openssl rand -hex 32"
}
}
}
-18
View File
@@ -1,18 +0,0 @@
[tool.commitizen]
name = "cz_customize"
tag_format = "vault/v$version"
ignored_tag_formats = ["*/v${version}", "v${version}"]
version_scheme = "semver"
version_provider = "scm"
update_changelog_on_bump = true
changelog_file = "CHANGELOG.md"
major_version_zero = true
annotated_tag = true
pre_bump_hooks = ["bash scripts/hook-bump-pre.sh"]
post_bump_hooks = ["goreleaser release --clean -f cmd/vault/.goreleaser.yml"]
[tool.commitizen.customize]
bump_pattern = "^(feat|fix|refactor|perf|BREAKING CHANGE)"
bump_map = { "BREAKING CHANGE" = "MAJOR", "feat" = "MINOR", "fix" = "PATCH", "refactor" = "PATCH", "perf" = "PATCH" }
default_bump = "PATCH"
changelog_pattern = "^(feat|fix|refactor|docs|build)\\(vault\\)(!)?:"
-71
View File
@@ -1,71 +0,0 @@
# yaml-language-server: $schema=https://goreleaser.com/static/schema-pro.json
---
version: 2
dist: dist/vault
monorepo:
tag_prefix: vault/
dir: cmd/vault
project_name: vault
before:
hooks:
- go mod download
builds:
- id: vault
main: main.go
binary: vault
no_unique_dist_dir: true
hooks:
post:
- cp dist/vault/vault.wasm x/dwn/client/plugin/vault.wasm
- cp dist/vault/vault.wasm packages/es/src/plugin/plugin.wasm
mod_timestamp: "{{ .CommitTimestamp }}"
env:
- CGO_ENABLED=0
goos:
- wasip1
goarch:
- wasm
flags:
- -mod=readonly
- -trimpath
ldflags:
- -s -w
- -X main.version={{.Version}}
- -X main.commit={{.Commit}}
- -X main.date={{.Date}}
archives:
- id: vault-wasm-archive
name_template: "vault_wasm_{{ .Version }}"
formats: ["binary"]
wrap_in_directory: true
blobs:
- provider: s3
endpoint: https://eb37925850388bca807b7fab964c12bb.r2.cloudflarestorage.com
bucket: releases
region: auto
directory: "vault/{{ .Tag }}"
release:
disable: false
github:
owner: sonr-io
name: sonr
name_template: "{{.ProjectName}}/{{ .Tag }}"
draft: false
replace_existing_draft: false # Don't replace drafts
replace_existing_artifacts: false # Append, don't replace
mode: append # Explicitly set to append mode
checksum:
name_template: "vault_checksums.txt"
snapshot:
version_template: "{{ incpatch .Version }}-dev"
# Changelog configuration
changelog:
sort: asc
-6
View File
@@ -1,6 +0,0 @@
## vault/v0.0.2 (2025-10-04)
## vault/v0.0.1 (2025-10-03)
- feat(vault): introduce assembly of the initial vault
-120
View File
@@ -1,120 +0,0 @@
#!/usr/bin/make -f
# Output configuration - dual output for both plugin and ES package
GIT_ROOT := $(shell git rev-parse --show-toplevel)
PLUGIN_DIR := $(GIT_ROOT)/x/dwn/client/plugin
ES_PACKAGE_DIR := $(GIT_ROOT)/packages/es/src/plugin
OUTPUT_FILE := plugin.wasm
PLUGIN_PATH := $(PLUGIN_DIR)/vault.wasm
ES_PATH := $(ES_PACKAGE_DIR)/$(OUTPUT_FILE)
# Build configuration for WASM
GOOS := wasip1
GOARCH := wasm
# Version information
VERSION := $(shell echo $(shell git describe --tags 2>/dev/null || echo "dev") | sed 's/^v//')
COMMIT := $(shell git log -1 --format='%H')
.PHONY: all build clean install test version help
all: build
build:
@echo "Building vault WASM module..."
@echo "Targets: Plugin and ES package"
@mkdir -p $(PLUGIN_DIR)
@mkdir -p $(ES_PACKAGE_DIR)
@GOOS=$(GOOS) GOARCH=$(GOARCH) go build -o $(PLUGIN_PATH) main.go
@cp $(PLUGIN_PATH) $(ES_PATH)
@echo "✅ Vault WASM module built successfully"
@echo "Plugin output: $(PLUGIN_PATH)"
@echo "ES package output: $(ES_PATH)"
@ls -lh $(PLUGIN_PATH) | awk '{print "Plugin size: " $$5}'
@ls -lh $(ES_PATH) | awk '{print "ES package size: " $$5}'
tidy:
@echo "Tidying vault build artifacts..."
@go mod tidy
@echo "✅ Tidy complete"
test:
@echo "Running vault tests..."
@go test -v ./...
@cd $(GIT_ROOT) && go test -C . -mod=readonly -v github.com/sonr-io/sonr/x/dwn/client/plugin/...
clean:
@echo "Cleaning vault build artifacts..."
@rm -f $(PLUGIN_PATH)
@rm -f $(ES_PATH)
@echo "✅ Clean complete"
release:
@echo "Creating vault release..."
@cd $(GIT_ROOT) && cz --config cmd/vault/.cz.toml --no-raise 6,21 bump --yes --increment PATCH
snapshot:
@echo "Dry-Run Bumping Vault version..."
@cd $(GIT_ROOT) && cz --config cmd/vault/.cz.toml bump --yes --dry-run --no-verify --increment PATCH
@echo "Creating vault snapshots for all platforms..."
@cd $(GIT_ROOT) && goreleaser release --snapshot --clean -f cmd/vault/.goreleaser.yml
version:
@echo "Vault WASM Module"
@echo "================="
@echo "Version: $(VERSION)"
@echo "Commit: $(COMMIT)"
@echo "Target OS: $(GOOS)"
@echo "Target Arch: $(GOARCH)"
@echo "Plugin output: $(PLUGIN_PATH)"
@echo "ES output: $(ES_PATH)"
verify: build
@echo "Verifying WASM modules..."
@if [ -f "$(PLUGIN_PATH)" ]; then \
file "$(PLUGIN_PATH)"; \
echo "✅ Plugin WASM file exists"; \
else \
echo "❌ Plugin WASM file not found"; \
exit 1; \
fi
@if [ -f "$(ES_PATH)" ]; then \
file "$(ES_PATH)"; \
echo "✅ ES package WASM file exists"; \
else \
echo "❌ ES package WASM file not found"; \
exit 1; \
fi
@echo "Plugin size: $$(du -h $(PLUGIN_PATH) | cut -f1)"
@echo "ES size: $$(du -h $(ES_PATH) | cut -f1)"
@echo "✅ Verification complete"
help:
@echo "Vault WASM Module Makefile"
@echo "=========================="
@echo ""
@echo "This Makefile builds the vault WebAssembly module for both the"
@echo "Sonr blockchain plugin system and the @sonr.io/es package."
@echo ""
@echo "Available targets:"
@echo " build - Build vault WASM module (default)"
@echo " clean - Remove built WASM artifacts"
@echo " test - Run vault tests"
@echo " tidy - Tidy Go module dependencies"
@echo " version - Display version information"
@echo " verify - Build and verify the WASM modules"
@echo " help - Show this help message"
@echo ""
@echo "Output locations:"
@echo " Plugin: $(PLUGIN_PATH)"
@echo " ES Package: $(ES_PATH)"
@echo ""
@echo "Integration:"
@echo " The WASM module is built for two purposes:"
@echo " 1. Plugin system in x/dwn/client/plugin"
@echo " 2. ES package for browser distribution via jsDelivr"
@echo ""
@echo "Examples:"
@echo " make build # Build WASM module to both locations"
@echo " make verify # Build and verify both outputs"
@echo " make clean # Remove all artifacts"
-477
View File
@@ -1,477 +0,0 @@
# Vault - WebAssembly Vault Plugin
Vault is a WebAssembly-based vault system for the Sonr blockchain that provides secure, isolated execution of cryptographic operations. Built using the Extism framework, Vault enables secure multi-party computation (MPC) and vault management within a sandboxed WebAssembly environment.
## Overview
Vault serves as a cryptographic vault system that:
- Provides secure enclave-based key generation and management
- Supports multi-chain transaction signing (Cosmos, EVM)
- Implements WebAuthn-based authentication
- Offers secure import/export functionality via IPFS
- Enables isolated execution through WebAssembly
## Architecture
### Core Components
- **MPC Enclave**: Multi-party computation system for secure key operations
- **Vault Management**: Create, unlock, and manage cryptographic vaults
- **IPFS Integration**: Secure backup and restore of encrypted vault data
- **WebAuthn Support**: Passwordless authentication for vault operations
- **Multi-Chain Support**: Transaction signing for different blockchain networks
### Build Configuration
Vault is built specifically for WebAssembly:
```go
//go:build js && wasm
// +build js,wasm
```
## API Reference
### Core Enclave Operations
#### `generate`
```go
//go:wasmexport generate
func generate() int32
```
Creates a new MPC enclave and returns the enclave data and public key.
**Input**: `GenerateRequest`
```json
{
"id": "string"
}
```
**Output**: `GenerateResponse`
```json
{
"data": "EnclaveData",
"public_key": "[]byte"
}
```
#### `refresh`
```go
//go:wasmexport refresh
func refresh() int32
```
Refreshes an existing enclave with new cryptographic material.
**Input**: `RefreshRequest`
```json
{
"enclave": "EnclaveData"
}
```
**Output**: `RefreshResponse`
```json
{
"okay": "bool",
"data": "EnclaveData"
}
```
#### `sign`
```go
//go:wasmexport sign
func sign() int32
```
Signs a message using the enclave's private key.
**Input**: `SignRequest`
```json
{
"message": "[]byte",
"enclave": "EnclaveData"
}
```
**Output**: `SignResponse`
```json
{
"signature": "[]byte"
}
```
#### `verify`
```go
//go:wasmexport verify
func verify() int32
```
Verifies a signature against a message and public key.
**Input**: `VerifyRequest`
```json
{
"public_key": "[]byte",
"message": "[]byte",
"signature": "[]byte"
}
```
**Output**: `VerifyResponse`
```json
{
"valid": "bool"
}
```
### Vault Import/Export Operations
#### `export`
```go
//go:wasmexport export
func export() int32
```
Encrypts and exports vault data to IPFS, returning a Content ID (CID).
**Input**: `ExportRequest`
```json
{
"enclave": "EnclaveData",
"password": "[]byte"
}
```
**Output**: `ExportResponse`
```json
{
"cid": "string",
"success": "bool"
}
```
#### `import`
```go
//go:wasmexport import
func importVault() int32
```
Retrieves and decrypts vault data from IPFS using a CID and password.
**Input**: `ImportRequest`
```json
{
"cid": "string",
"password": "[]byte"
}
```
**Output**: `ImportResponse`
```json
{
"enclave": "EnclaveData",
"success": "bool"
}
```
### Advanced Vault Operations
#### `create_vault_enclave`
```go
//go:wasmexport create_vault_enclave
func createVaultEnclave() int32
```
Creates a new vault enclave with advanced configuration options.
**Input**: `EnclaveConfig`
```json
{
"vault_id": "string",
"key_derivation_method": "string",
"encryption_algorithm": "string",
"signing_algorithm": "string",
"webauthn_enabled": "bool",
"auto_lock_timeout": "int64",
"key_rotation_interval": "int64",
"supported_chains": ["string"],
"max_concurrent_ops": "int",
"memory_limit": "uint64"
}
```
#### `unlock_vault_enclave`
```go
//go:wasmexport unlock_vault_enclave
func unlockVaultEnclave() int32
```
Unlocks a vault enclave, optionally using WebAuthn authentication.
#### `lock_vault_enclave`
```go
//go:wasmexport lock_vault_enclave
func lockVaultEnclave() int32
```
Locks a vault enclave to prevent unauthorized access.
#### `rotate_vault_key`
```go
//go:wasmexport rotate_vault_key
func rotateVaultKey() int32
```
Rotates the cryptographic keys within a vault enclave.
### Multi-Chain Transaction Signing
#### `sign_cosmos_transaction`
```go
//go:wasmexport sign_cosmos_transaction
func signCosmosTransaction() int32
```
Signs transactions for Cosmos SDK-based blockchains.
#### `sign_evm_transaction`
```go
//go:wasmexport sign_evm_transaction
func signEvmTransaction() int32
```
Signs transactions for Ethereum Virtual Machine compatible chains.
#### `sign_message`
```go
//go:wasmexport sign_message
func signMessage() int32
```
Signs arbitrary messages using the vault's private key.
### Health and Monitoring
#### `get_vault_health`
```go
//go:wasmexport get_vault_health
func getVaultHealth() int32
```
Returns the health status of a vault enclave.
**Output**: `EnclaveHealth`
```json
{
"vault_id": "string",
"status": "string",
"last_activity": "int64",
"key_rotation_due": "bool",
"attestation_valid": "bool"
}
```
## Configuration
### Environment Variables
Motor supports configuration through Extism variables:
- `chain_id`: Blockchain network identifier (default: "sonr-testnet-1")
- `password`: Default password for enclave operations (default: "password")
- `gateway`: IPFS gateway URL (default: "https://ipfs.did.run/ipfs/")
Access these via helper functions:
```go
func GetChainID() string
func GetPassword() []byte
func GetGateway() string
```
### IPFS Integration
Motor integrates with IPFS for secure vault backup and restore:
- **Storage Endpoint**: `http://127.0.0.1:5001/api/v0/add`
- **Retrieval Endpoint**: `http://127.0.0.1:5001/api/v0/cat`
- **Data Format**: Encrypted vault data stored as content-addressed objects
- **Security**: All vault data is encrypted before IPFS storage
## Security Features
### Enclave Isolation
- WebAssembly sandbox provides memory isolation
- Secure execution environment prevents side-channel attacks
- Attestation mechanisms ensure enclave integrity
### Authentication
- WebAuthn support for passwordless authentication
- Challenge-response authentication flows
- Automatic vault locking with configurable timeouts
### Key Management
- Multi-party computation for enhanced security
- Automatic key rotation with configurable intervals
- Secure key derivation and storage
### Data Protection
- AES encryption for sensitive data
- Password-based encryption for import/export
- Secure memory handling within WASM environment
## Usage Examples
### Basic Enclave Operations
```javascript
// Generate new enclave
const generateReq = { id: "my-vault" };
const result = call_wasm_function("generate", generateReq);
// Sign a message
const signReq = {
message: new Uint8Array([1, 2, 3, 4]),
enclave: result.data,
};
const signature = call_wasm_function("sign", signReq);
```
### Vault Management
```javascript
// Create vault with configuration
const config = {
vault_id: "user-vault-001",
webauthn_enabled: true,
auto_lock_timeout: 300,
supported_chains: ["cosmos", "ethereum"],
};
const vault = call_wasm_function("create_vault_enclave", config);
// Sign Cosmos transaction
const cosmosReq = {
vault_id: "user-vault-001",
chain_type: "cosmos",
chain_id: "cosmoshub-4",
message: transactionBytes,
};
const cosmosResult = call_wasm_function("sign_cosmos_transaction", cosmosReq);
```
### Import/Export Operations
```javascript
// Export vault to IPFS
const exportReq = {
enclave: vaultData,
password: new Uint8Array([
/* password bytes */
]),
};
const exportResult = call_wasm_function("export", exportReq);
console.log("Vault exported to CID:", exportResult.cid);
// Import vault from IPFS
const importReq = {
cid: "QmXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXx",
password: new Uint8Array([
/* password bytes */
]),
};
const importResult = call_wasm_function("import", importReq);
```
## Building and Deployment
### Prerequisites
- Go 1.24.4+
- Extism runtime
- IPFS node (for import/export functionality)
### Build Commands
```bash
# Build WebAssembly module
GOOS=js GOARCH=wasm go build -o motr.wasm main.go
# Build via Makefile
make motr
```
### Integration
Motor is designed to be integrated with:
- **Highway Service**: PostgreSQL-backed HTTP API
- **Sonr Blockchain**: Cosmos SDK-based blockchain node
- **IPFS Network**: Decentralized storage system
- **WebAuthn Infrastructure**: Passwordless authentication
## Error Handling
All functions return `int32` status codes:
- `0`: Success
- `1`: Error (details available via `pdk.SetError`)
Error information is logged using Extism's logging system:
```go
pdk.Log(pdk.LogError, "Error message")
pdk.Log(pdk.LogInfo, "Info message")
```
## Dependencies
### Core Dependencies
- `github.com/extism/go-pdk`: WebAssembly plugin development kit
- `github.com/sonr-io/sonr/crypto/mpc`: Multi-party computation library
### Cryptographic Libraries
- `filippo.io/edwards25519`: Edwards25519 elliptic curve
- `github.com/btcsuite/btcd/btcec/v2`: Bitcoin cryptography
- `github.com/consensys/gnark-crypto`: Zero-knowledge proof cryptography
## License
Motor is part of the Sonr blockchain project. See the project's main license for terms and conditions.
-26
View File
@@ -1,26 +0,0 @@
module vault
go 1.24.7
replace github.com/sonr-io/sonr/crypto => ../../crypto/
require (
github.com/extism/go-pdk v1.1.3
github.com/golang-jwt/jwt/v5 v5.3.0
github.com/sonr-io/sonr/crypto v0.0.0-00010101000000-000000000000
)
require (
filippo.io/edwards25519 v1.1.0 // indirect
github.com/bits-and-blooms/bitset v1.24.0 // indirect
github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect
github.com/bwesterb/go-ristretto v1.2.3 // indirect
github.com/consensys/gnark-crypto v0.19.0 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 // indirect
github.com/dustinxie/ecc v0.0.0-20210511000915-959544187564 // indirect
github.com/gtank/merlin v0.1.1 // indirect
github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643 // indirect
github.com/pkg/errors v0.9.1 // indirect
golang.org/x/crypto v0.42.0 // indirect
golang.org/x/sys v0.36.0 // indirect
)
-38
View File
@@ -1,38 +0,0 @@
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
github.com/bits-and-blooms/bitset v1.24.0 h1:H4x4TuulnokZKvHLfzVRTHJfFfnHEeSYJizujEZvmAM=
github.com/bits-and-blooms/bitset v1.24.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
github.com/btcsuite/btcd/btcec/v2 v2.3.4 h1:3EJjcN70HCu/mwqlUsGK8GcNVyLVxFDlWurTXGPFfiQ=
github.com/btcsuite/btcd/btcec/v2 v2.3.4/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04=
github.com/bwesterb/go-ristretto v1.2.3 h1:1w53tCkGhCQ5djbat3+MH0BAQ5Kfgbt56UZQ/JMzngw=
github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
github.com/consensys/gnark-crypto v0.19.0 h1:zXCqeY2txSaMl6G5wFpZzMWJU9HPNh8qxPnYJ1BL9vA=
github.com/consensys/gnark-crypto v0.19.0/go.mod h1:rT23F0XSZqE0mUA0+pRtnL56IbPxs6gp4CeRsBk4XS0=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 h1:NMZiJj8QnKe1LgsbDayM4UoHwbvwDRwnI3hwNaAHRnc=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0/go.mod h1:ZXNYxsqcloTdSy/rNShjYzMhyjf0LaoftYK0p+A3h40=
github.com/dustinxie/ecc v0.0.0-20210511000915-959544187564 h1:I6KUy4CI6hHjqnyJLNCEi7YHVMkwwtfSr2k9splgdSM=
github.com/dustinxie/ecc v0.0.0-20210511000915-959544187564/go.mod h1:yekO+3ZShy19S+bsmnERmznGy9Rfg6dWWWpiGJjNAz8=
github.com/extism/go-pdk v1.1.3 h1:hfViMPWrqjN6u67cIYRALZTZLk/enSPpNKa+rZ9X2SQ=
github.com/extism/go-pdk v1.1.3/go.mod h1:Gz+LIU/YCKnKXhgge8yo5Yu1F/lbv7KtKFkiCSzW/P4=
github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo=
github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE=
github.com/gtank/merlin v0.1.1 h1:eQ90iG7K9pOhtereWsmyRJ6RAwcP4tHTDBHXNg+u5is=
github.com/gtank/merlin v0.1.1/go.mod h1:T86dnYJhcGOh5BjZFCJWTDeTK7XW8uE+E21Cy/bIQ+s=
github.com/leanovate/gopter v0.2.11 h1:vRjThO1EKPb/1NsDXuDrzldR28RLkBflWYcU9CvzWu4=
github.com/leanovate/gopter v0.2.11/go.mod h1:aK3tzZP/C+p1m3SPRE4SYZFGP7jjkuSI4f7Xvpt0S9c=
github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643 h1:hLDRPB66XQT/8+wG9WsDpiCvZf1yKO7sz7scAjSlBa0=
github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643/go.mod h1:43+3pMjjKimDBf5Kr4ZFNGbLql1zKkbImw+fZbw3geM=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
golang.org/x/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI=
golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8=
golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-483
View File
@@ -1,483 +0,0 @@
//go:build js && wasm
// +build js,wasm
package main
import (
"crypto/sha256"
"encoding/json"
"fmt"
"time"
"github.com/extism/go-pdk"
"github.com/golang-jwt/jwt/v5"
"github.com/sonr-io/sonr/crypto/mpc"
)
const (
KeyChainID = "chain_id"
KeyEnclave = "enclave"
KeyVaultConfig = "vault_config"
)
// GetChainID returns the chain ID to use for unlocking the enclave
func GetChainID() string {
v := pdk.GetVar(KeyChainID)
if v == nil {
return "sonr-testnet-1"
}
return string(v)
}
// GetEnclaveData loads MPC enclave data from PDK environment
func GetEnclaveData() (*mpc.EnclaveData, error) {
v := pdk.GetVar(KeyEnclave)
if v == nil {
return nil, fmt.Errorf("enclave data not provided in environment")
}
var data mpc.EnclaveData
if err := json.Unmarshal(v, &data); err != nil {
return nil, fmt.Errorf("failed to unmarshal enclave data: %w", err)
}
return &data, nil
}
// GetVaultConfig loads vault configuration from PDK environment
func GetVaultConfig() map[string]any {
v := pdk.GetVar(KeyVaultConfig)
if v == nil {
return make(map[string]any)
}
var config map[string]any
if err := json.Unmarshal(v, &config); err != nil {
pdk.Log(pdk.LogWarn, fmt.Sprintf("Failed to parse vault config: %v", err))
return make(map[string]any)
}
return config
}
// UCAN Token Request/Response types
type NewOriginTokenRequest struct {
AudienceDID string `json:"audience_did"`
Attenuations []map[string]any `json:"attenuations,omitempty"`
Facts []string `json:"facts,omitempty"`
NotBefore int64 `json:"not_before,omitempty"`
ExpiresAt int64 `json:"expires_at,omitempty"`
}
type NewAttenuatedTokenRequest struct {
ParentToken string `json:"parent_token"`
AudienceDID string `json:"audience_did"`
Attenuations []map[string]any `json:"attenuations,omitempty"`
Facts []string `json:"facts,omitempty"`
NotBefore int64 `json:"not_before,omitempty"`
ExpiresAt int64 `json:"expires_at,omitempty"`
}
type UCANTokenResponse struct {
Token string `json:"token"`
Issuer string `json:"issuer"`
Address string `json:"address"`
Error string `json:"error,omitempty"`
}
type SignDataRequest struct {
Data []byte `json:"data"`
}
type SignDataResponse struct {
Signature []byte `json:"signature"`
Error string `json:"error,omitempty"`
}
type VerifyDataRequest struct {
Data []byte `json:"data"`
Signature []byte `json:"signature"`
}
type VerifyDataResponse struct {
Valid bool `json:"valid"`
Error string `json:"error,omitempty"`
}
type GetIssuerDIDResponse struct {
IssuerDID string `json:"issuer_did"`
Address string `json:"address"`
ChainCode string `json:"chain_code"`
Error string `json:"error,omitempty"`
}
var (
enclave mpc.Enclave
issuerDID string
address string
)
func main() {
// Initialize MPC enclave from PDK environment
if err := initializeEnclave(); err != nil {
pdk.SetError(fmt.Errorf("failed to initialize enclave: %w", err))
return
}
pdk.Log(pdk.LogInfo, "Motor plugin initialized as MPC-based UCAN source")
}
// initializeEnclave initializes the MPC enclave from PDK environment
func initializeEnclave() error {
// Load enclave data from PDK environment
enclaveData, err := GetEnclaveData()
if err != nil {
return fmt.Errorf("failed to get enclave data: %w", err)
}
// Import MPC enclave from data
enclave, err = mpc.ImportEnclave(mpc.WithEnclaveData(enclaveData))
if err != nil {
return fmt.Errorf("failed to import enclave: %w", err)
}
// Derive issuer DID and address from enclave public key
pubKeyBytes := enclave.PubKeyBytes()
issuerDID, address, err = deriveIssuerDIDFromBytes(pubKeyBytes)
if err != nil {
return fmt.Errorf("failed to derive issuer DID: %w", err)
}
return nil
}
//go:wasmexport new_origin_token
func newOriginToken() int32 {
if !enclave.IsValid() {
pdk.SetError(fmt.Errorf("enclave not initialized"))
return 1
}
req := &NewOriginTokenRequest{}
err := pdk.InputJSON(req)
if err != nil {
pdk.SetError(fmt.Errorf("failed to parse request: %w", err))
return 1
}
// Convert timestamps
var notBefore, expiresAt time.Time
if req.NotBefore > 0 {
notBefore = time.Unix(req.NotBefore, 0)
}
if req.ExpiresAt > 0 {
expiresAt = time.Unix(req.ExpiresAt, 0)
}
// Create origin token using MPC signing
tokenString, err := createUCANToken(
req.AudienceDID,
nil,
req.Attenuations,
req.Facts,
notBefore,
expiresAt,
)
if err != nil {
resp := &UCANTokenResponse{Error: err.Error()}
pdk.OutputJSON(resp)
return 1
}
resp := &UCANTokenResponse{
Token: tokenString,
Issuer: issuerDID,
Address: address,
}
pdk.OutputJSON(resp)
return 0
}
//go:wasmexport new_attenuated_token
func newAttenuatedToken() int32 {
if !enclave.IsValid() {
pdk.SetError(fmt.Errorf("enclave not initialized"))
return 1
}
req := &NewAttenuatedTokenRequest{}
err := pdk.InputJSON(req)
if err != nil {
pdk.SetError(fmt.Errorf("failed to parse request: %w", err))
return 1
}
// Convert timestamps
var notBefore, expiresAt time.Time
if req.NotBefore > 0 {
notBefore = time.Unix(req.NotBefore, 0)
}
if req.ExpiresAt > 0 {
expiresAt = time.Unix(req.ExpiresAt, 0)
}
// Create proofs from parent token
proofs := []string{req.ParentToken}
// Create attenuated token using MPC signing
tokenString, err := createUCANToken(
req.AudienceDID,
proofs,
req.Attenuations,
req.Facts,
notBefore,
expiresAt,
)
if err != nil {
resp := &UCANTokenResponse{Error: err.Error()}
pdk.OutputJSON(resp)
return 1
}
resp := &UCANTokenResponse{
Token: tokenString,
Issuer: issuerDID,
Address: address,
}
pdk.OutputJSON(resp)
return 0
}
//go:wasmexport sign_data
func signData() int32 {
if !enclave.IsValid() {
pdk.SetError(fmt.Errorf("enclave not initialized"))
return 1
}
req := &SignDataRequest{}
err := pdk.InputJSON(req)
if err != nil {
pdk.SetError(fmt.Errorf("failed to parse request: %w", err))
return 1
}
// Sign data using MPC enclave
signature, err := enclave.Sign(req.Data)
if err != nil {
resp := &SignDataResponse{Error: err.Error()}
pdk.OutputJSON(resp)
return 1
}
resp := &SignDataResponse{Signature: signature}
pdk.OutputJSON(resp)
return 0
}
//go:wasmexport verify_data
func verifyData() int32 {
if !enclave.IsValid() {
pdk.SetError(fmt.Errorf("enclave not initialized"))
return 1
}
req := &VerifyDataRequest{}
err := pdk.InputJSON(req)
if err != nil {
pdk.SetError(fmt.Errorf("failed to parse request: %w", err))
return 1
}
// Verify data using MPC enclave
valid, err := enclave.Verify(req.Data, req.Signature)
if err != nil {
resp := &VerifyDataResponse{Error: err.Error()}
pdk.OutputJSON(resp)
return 1
}
resp := &VerifyDataResponse{Valid: valid}
pdk.OutputJSON(resp)
return 0
}
//go:wasmexport get_issuer_did
func getIssuerDID() int32 {
if !enclave.IsValid() {
pdk.SetError(fmt.Errorf("enclave not initialized"))
return 1
}
// Get chain code for deterministic derivation
chainCode, err := getChainCode()
if err != nil {
resp := &GetIssuerDIDResponse{Error: err.Error()}
pdk.OutputJSON(resp)
return 1
}
resp := &GetIssuerDIDResponse{
IssuerDID: issuerDID,
Address: address,
ChainCode: fmt.Sprintf("%x", chainCode),
}
pdk.OutputJSON(resp)
return 0
}
// UCAN token creation and MPC signing implementation
// MPCSigningMethod implements JWT signing using MPC enclaves
type MPCSigningMethod struct {
Name string
enclave mpc.Enclave
}
// Alg returns the signing method algorithm name
func (m *MPCSigningMethod) Alg() string {
return m.Name
}
// Sign signs a JWT string using the MPC enclave
func (m *MPCSigningMethod) Sign(signingString string, key any) ([]byte, error) {
// Hash the signing string
hasher := sha256.New()
hasher.Write([]byte(signingString))
digest := hasher.Sum(nil)
// Use MPC enclave to sign the digest
sig, err := m.enclave.Sign(digest)
if err != nil {
return nil, fmt.Errorf("failed to sign with MPC: %w", err)
}
return sig, nil
}
// Verify verifies a JWT signature using the MPC enclave
func (m *MPCSigningMethod) Verify(signingString string, sig []byte, key any) error {
// Hash the signing string
hasher := sha256.New()
hasher.Write([]byte(signingString))
digest := hasher.Sum(nil)
// Use MPC enclave to verify signature
valid, err := m.enclave.Verify(digest, sig)
if err != nil {
return fmt.Errorf("failed to verify signature: %w", err)
}
if !valid {
return fmt.Errorf("signature verification failed")
}
return nil
}
// createUCANToken creates a UCAN token using MPC signing
func createUCANToken(
audienceDID string,
proofs []string,
attenuations []map[string]any,
facts []string,
notBefore, expiresAt time.Time,
) (string, error) {
// Validate audience DID
if audienceDID == "" {
return "", fmt.Errorf("audience DID is required")
}
// Create MPC signing method
signingMethod := &MPCSigningMethod{
Name: "MPC256",
enclave: enclave,
}
// Create JWT token
token := jwt.New(signingMethod)
// Set UCAN version in header
token.Header["ucv"] = "0.9.0"
// Prepare time claims
var nbfUnix, expUnix int64
if !notBefore.IsZero() {
nbfUnix = notBefore.Unix()
}
if !expiresAt.IsZero() {
expUnix = expiresAt.Unix()
}
// Set claims
claims := jwt.MapClaims{
"iss": issuerDID,
"aud": audienceDID,
}
// Add attenuations if provided
if len(attenuations) > 0 {
claims["att"] = attenuations
}
// Add proofs if provided
if len(proofs) > 0 {
claims["prf"] = proofs
}
// Add facts if provided
if len(facts) > 0 {
claims["fct"] = facts
}
// Add time claims
if nbfUnix > 0 {
claims["nbf"] = nbfUnix
}
if expUnix > 0 {
claims["exp"] = expUnix
}
token.Claims = claims
// Sign the token using MPC enclave (key parameter is ignored for MPC signing)
tokenString, err := token.SignedString(nil)
if err != nil {
return "", fmt.Errorf("failed to sign token with MPC: %w", err)
}
return tokenString, nil
}
// deriveIssuerDIDFromBytes creates issuer DID and address from public key bytes
func deriveIssuerDIDFromBytes(pubKeyBytes []byte) (string, string, error) {
if len(pubKeyBytes) == 0 {
return "", "", fmt.Errorf("empty public key bytes")
}
// Generate address from public key (simplified implementation)
address := fmt.Sprintf("sonr1%x", pubKeyBytes[:20])
// Create DID from address (simplified implementation)
issuerDID := fmt.Sprintf("did:sonr:%s", address)
return issuerDID, address, nil
}
// getChainCode derives a deterministic chain code from the enclave
func getChainCode() ([]byte, error) {
if !enclave.IsValid() {
return nil, fmt.Errorf("enclave is not valid")
}
// Sign the address to create a deterministic chain code
sig, err := enclave.Sign([]byte(address))
if err != nil {
return nil, fmt.Errorf("failed to sign address for chain code: %w", err)
}
// Hash the signature to create a 32-byte chain code
hasher := sha256.New()
hasher.Write(sig)
hash := hasher.Sum(nil)
return hash[:32], nil
}
-4
View File
@@ -1,4 +0,0 @@
package main
// Version is set by commitizen during release process
var Version = "dev"