-
Notifications
You must be signed in to change notification settings - Fork 200
SDK Go version #907
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
SDK Go version #907
Changes from all commits
3ef30ed
34e0958
b89c8b7
a50bf52
ef849af
f29e574
823c33b
90e2dc6
644b2b6
19b287f
7c4618f
4e9d0aa
fcc42bb
da58e7d
e2a1d72
30d8a92
e0c5b1b
42f081a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,48 @@ | ||||||
| package self | ||||||
|
|
||||||
| import ( | ||||||
| "context" | ||||||
|
|
||||||
| ) | ||||||
|
|
||||||
| // GetActionIdFunc is a function type for custom action ID generation | ||||||
| type GetActionIdFunc func(ctx context.Context, userIdentifier string, userDefinedData string) (string, error) | ||||||
|
|
||||||
| // InMemoryConfigStore provides an in-memory implementation of ConfigStore with custom action ID logic | ||||||
| type InMemoryConfigStore struct { | ||||||
| configs map[string]VerificationConfig | ||||||
| getActionIdFunc GetActionIdFunc | ||||||
| } | ||||||
|
|
||||||
| // Compile-time check to ensure InMemoryConfigStore implements ConfigStore interface | ||||||
| var _ ConfigStore = (*InMemoryConfigStore)(nil) | ||||||
|
|
||||||
| // NewInMemoryConfigStore creates a new instance of InMemoryConfigStore | ||||||
| func NewInMemoryConfigStore(getActionIdFunc GetActionIdFunc) *InMemoryConfigStore { | ||||||
| return &InMemoryConfigStore{ | ||||||
| configs: make(map[string]VerificationConfig), | ||||||
| getActionIdFunc: getActionIdFunc, | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| // GetActionId uses the custom function to generate action IDs | ||||||
| func (store *InMemoryConfigStore) GetActionId(ctx context.Context, userIdentifier string, userDefinedData string) (string, error) { | ||||||
| return store.getActionIdFunc(ctx, userIdentifier, userDefinedData) | ||||||
| } | ||||||
|
|
||||||
| // SetConfig stores a configuration with the given ID | ||||||
| // Returns true if the configuration was newly created, false if it was updated | ||||||
| func (store *InMemoryConfigStore) SetConfig(ctx context.Context, id string, config VerificationConfig) (bool, error) { | ||||||
| _, existed := store.configs[id] | ||||||
| store.configs[id] = config | ||||||
| return !existed, nil | ||||||
| } | ||||||
|
Comment on lines
+12
to
+39
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. InMemoryConfigStore lacks thread safety The Add a mutex for thread-safe operations: +import (
+ "context"
+ "sync"
+)
// InMemoryConfigStore provides an in-memory implementation of ConfigStore with custom action ID logic
type InMemoryConfigStore struct {
configs map[string]VerificationConfig
getActionIdFunc GetActionIdFunc
+ mu sync.RWMutex
}
// SetConfig stores a configuration with the given ID
func (store *InMemoryConfigStore) SetConfig(ctx context.Context, id string, config VerificationConfig) (bool, error) {
+ store.mu.Lock()
+ defer store.mu.Unlock()
_, existed := store.configs[id]
store.configs[id] = config
return !existed, nil
}
// GetConfig retrieves a configuration by ID
func (store *InMemoryConfigStore) GetConfig(ctx context.Context, id string) (VerificationConfig, error) {
+ store.mu.RLock()
+ defer store.mu.RUnlock()
config, exists := store.configs[id]
if !exists {
return VerificationConfig{}, nil
}
return config, nil
}
🤖 Prompt for AI Agents |
||||||
|
|
||||||
| // GetConfig retrieves a configuration by ID | ||||||
| func (store *InMemoryConfigStore) GetConfig(ctx context.Context, id string) (VerificationConfig, error) { | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix indentation issue There's an incorrect indentation at the beginning of this line. - func (store *InMemoryConfigStore) GetConfig(ctx context.Context, id string) (VerificationConfig, error) {
+func (store *InMemoryConfigStore) GetConfig(ctx context.Context, id string) (VerificationConfig, error) {📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||
| config, exists := store.configs[id] | ||||||
| if !exists { | ||||||
| return VerificationConfig{}, nil | ||||||
| } | ||||||
| return config, nil | ||||||
| } | ||||||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,294 @@ | ||||||
| # Self Protocol Go SDK | ||||||
|
|
||||||
| A Go SDK for integrating with the Self protocol for privacy-preserving identity verification using zero-knowledge proofs and passport/ID card attestations. | ||||||
|
|
||||||
| ## Installation | ||||||
|
|
||||||
| ```bash | ||||||
| go get github.com/selfxyz/self/sdk/sdk-go@main | ||||||
| ``` | ||||||
|
|
||||||
| ## Quick Start | ||||||
|
|
||||||
| ### Basic Usage | ||||||
|
|
||||||
| ```go | ||||||
| package main | ||||||
|
|
||||||
| import ( | ||||||
| "context" | ||||||
| "fmt" | ||||||
| "log" | ||||||
|
|
||||||
| "github.com/selfxyz/self/sdk/sdk-go" | ||||||
| "github.com/selfxyz/self/sdk/sdk-go/common" | ||||||
| ) | ||||||
|
|
||||||
| func main() { | ||||||
| // Create a verification configuration | ||||||
| config := self.VerificationConfig{ | ||||||
| MinimumAge: &[]int{18}[0], // Require 18+ years | ||||||
| ExcludedCountries: []common.Country3LetterCode{common.USA}, // Exclude USA | ||||||
| Ofac: &[]bool{false}[0], // Allow OFAC flagged individuals | ||||||
| } | ||||||
|
|
||||||
| // Create a config store | ||||||
| configStore := self.NewDefaultConfigStore(config) | ||||||
|
|
||||||
| // Define allowed attestation types | ||||||
| allowedIds := map[self.AttestationId]bool{ | ||||||
| self.Passport: true, | ||||||
| self.EUCard: true, | ||||||
| } | ||||||
|
|
||||||
| // Initialize the verifier | ||||||
| verifier, err := self.NewBackendVerifier( | ||||||
| "my-app-scope", // Your application scope | ||||||
| "https://my-app.com", // Your application endpoint | ||||||
| false, // Use mainnet (true for testnet) | ||||||
| allowedIds, // Allowed attestation types | ||||||
| configStore, // Configuration storage | ||||||
| self.UserIDTypeHex, // User identifier type | ||||||
| ) | ||||||
| if err != nil { | ||||||
| log.Fatal(err) | ||||||
| } | ||||||
|
|
||||||
| // Verify a proof (these would come from your frontend) | ||||||
| ctx := context.Background() | ||||||
| result, err := verifier.Verify( | ||||||
| ctx, | ||||||
| "1", // Attestation ID (passport) | ||||||
| proof, // Zero-knowledge proof from frontend | ||||||
| publicSignals, // Public signals from frontend | ||||||
| userContextData, // User context data from frontend | ||||||
| ) | ||||||
| if err != nil { | ||||||
| log.Printf("Verification failed: %v", err) | ||||||
| return | ||||||
| } | ||||||
|
|
||||||
| // Check verification results | ||||||
| if result.IsValidDetails.IsValid { | ||||||
| fmt.Printf("✅ Verification successful!\n") | ||||||
| fmt.Printf("User ID: %s\n", result.UserData.UserIdentifier) | ||||||
| fmt.Printf("Age verification: %v\n", result.IsValidDetails.IsMinimumAgeValid) | ||||||
| fmt.Printf("OFAC verification: %v\n", result.IsValidDetails.IsOfacValid) | ||||||
| fmt.Printf("Nationality: %s\n", result.DiscloseOutput.Nationality) | ||||||
| } else { | ||||||
| fmt.Printf("❌ Verification failed\n") | ||||||
| } | ||||||
| } | ||||||
| ``` | ||||||
|
|
||||||
| ## Configuration | ||||||
|
|
||||||
| ### Verification Config | ||||||
|
|
||||||
| The `VerificationConfig` struct allows you to specify verification requirements: | ||||||
|
|
||||||
| ```go | ||||||
| type VerificationConfig struct { | ||||||
| MinimumAge *int // Minimum age requirement (nil to disable) | ||||||
| ExcludedCountries []common.Country3LetterCode // Countries to exclude | ||||||
| Ofac *bool // OFAC compliance (nil to ignore) | ||||||
| } | ||||||
| ``` | ||||||
|
|
||||||
| ### Config Storage | ||||||
|
|
||||||
| Implement the `ConfigStore` interface for custom configuration management: | ||||||
|
|
||||||
| ```go | ||||||
| type ConfigStore interface { | ||||||
| GetConfig(ctx context.Context, id string) (VerificationConfig, error) | ||||||
| SetConfig(ctx context.Context, id string, config VerificationConfig) (bool, error) | ||||||
| GetActionId(ctx context.Context, userIdentifier string, actionId string) (string, error) | ||||||
| } | ||||||
| ``` | ||||||
|
|
||||||
| For simple use cases, use `DefaultConfigStore`: | ||||||
|
|
||||||
| ```go | ||||||
| configStore := self.NewDefaultConfigStore(config) | ||||||
| ``` | ||||||
|
|
||||||
| For more complex scenarios, implement your own: | ||||||
|
|
||||||
| ```go | ||||||
| type DatabaseConfigStore struct { | ||||||
| db *sql.DB | ||||||
| } | ||||||
|
|
||||||
| func (d *DatabaseConfigStore) GetConfig(ctx context.Context, id string) (self.VerificationConfig, error) { | ||||||
| // Your database logic here | ||||||
| } | ||||||
|
|
||||||
| func (d *DatabaseConfigStore) SetConfig(ctx context.Context, id string, config self.VerificationConfig) (bool, error) { | ||||||
| // Your database logic here | ||||||
| } | ||||||
|
|
||||||
| func (d *DatabaseConfigStore) GetActionId(ctx context.Context, userIdentifier string, actionId string) (string, error) { | ||||||
| // Your database logic here | ||||||
| } | ||||||
| ``` | ||||||
|
|
||||||
| ## Attestation Types | ||||||
|
|
||||||
| The SDK supports two attestation types: | ||||||
|
|
||||||
| - `self.Passport`: Traditional passport verification | ||||||
| - `self.EUCard`: European ID card verification | ||||||
|
|
||||||
| ## Network Configuration | ||||||
|
|
||||||
| ### Mainnet (Production) | ||||||
| ```go | ||||||
| verifier, err := self.NewBackendVerifier( | ||||||
| scope, endpoint, false, // mockPassport = false for mainnet | ||||||
| allowedIds, configStore, userIdType, | ||||||
| ) | ||||||
| ``` | ||||||
|
|
||||||
| ### Testnet (Development) | ||||||
| ```go | ||||||
| verifier, err := self.NewBackendVerifier( | ||||||
| scope, endpoint, true, // mockPassport = true for testnet | ||||||
| allowedIds, configStore, userIdType, | ||||||
| ) | ||||||
| ``` | ||||||
|
|
||||||
| ## User Identifier Types | ||||||
|
|
||||||
| Choose how user identifiers are formatted: | ||||||
|
|
||||||
| ```go | ||||||
| self.UserIDTypeHex // Hex format: 0x1234... | ||||||
| self.UserIDTypeUUID // UUID format: 12345678-1234-1234-1234-123456789abc | ||||||
| ``` | ||||||
|
|
||||||
| ## Country Codes | ||||||
|
|
||||||
| Use 3-letter ISO country codes for exclusions: | ||||||
|
|
||||||
| ```go | ||||||
| import "github.com/self/sdk/common" | ||||||
|
|
||||||
coderabbitai[bot] marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
| excludedCountries := []common.Country3LetterCode{ | ||||||
| common.USA, // United States | ||||||
| common.RUS, // Russia | ||||||
| common.CHN, // China | ||||||
| } | ||||||
| ``` | ||||||
|
|
||||||
| ## Error Handling | ||||||
|
|
||||||
| The SDK provides detailed error information through `ConfigMismatchError`: | ||||||
|
|
||||||
| ```go | ||||||
| result, err := verifier.Verify(ctx, attestationId, proof, signals, contextData) | ||||||
| if err != nil { | ||||||
| if configErr, ok := err.(*self.ConfigMismatchError); ok { | ||||||
| fmt.Println("Configuration issues:") | ||||||
| for _, issue := range configErr.Issues { | ||||||
| fmt.Printf("- %s: %s\n", issue.Type, issue.Message) | ||||||
| } | ||||||
| } else { | ||||||
| fmt.Printf("Other error: %v\n", err) | ||||||
| } | ||||||
| return | ||||||
| } | ||||||
| ``` | ||||||
|
|
||||||
| ## Verification Result | ||||||
|
|
||||||
| The `VerificationResult` contains comprehensive verification information: | ||||||
|
|
||||||
| ```go | ||||||
| type VerificationResult struct { | ||||||
| AttestationId AttestationId // Type of attestation verified | ||||||
| IsValidDetails IsValidDetails // Validation status details | ||||||
| ForbiddenCountriesList []string // List of forbidden countries | ||||||
| DiscloseOutput GenericDiscloseOutput // Disclosed identity information | ||||||
| UserData UserData // User-specific data | ||||||
| } | ||||||
|
|
||||||
| type IsValidDetails struct { | ||||||
| IsValid bool // Overall proof validity | ||||||
| IsMinimumAgeValid bool // Age requirement met | ||||||
| IsOfacValid bool // OFAC compliance | ||||||
| } | ||||||
|
|
||||||
| type GenericDiscloseOutput struct { | ||||||
| Nullifier string // Unique nullifier for this proof | ||||||
| IssuingState string // Country that issued the document | ||||||
| Name string // Full name | ||||||
| IdNumber string // Document ID number | ||||||
| Nationality string // Nationality | ||||||
| DateOfBirth string // Date of birth | ||||||
| Gender string // Gender | ||||||
| ExpiryDate string // Document expiry date | ||||||
| MinimumAge string // Minimum age disclosed | ||||||
| Ofac []bool // OFAC check results | ||||||
| } | ||||||
| ``` | ||||||
|
|
||||||
| ## Examples | ||||||
|
|
||||||
| ### Age Verification (18+) | ||||||
|
|
||||||
| ```go | ||||||
| config := self.VerificationConfig{ | ||||||
| MinimumAge: &[]int{18}[0], | ||||||
| } | ||||||
| ``` | ||||||
|
|
||||||
| ### Country Restrictions | ||||||
|
|
||||||
| ```go | ||||||
| config := self.VerificationConfig{ | ||||||
| ExcludedCountries: []common.Country3LetterCode{ | ||||||
| common.USA, | ||||||
| common.RUS, | ||||||
| common.IRN, | ||||||
| }, | ||||||
| } | ||||||
| ``` | ||||||
|
|
||||||
| ### OFAC Compliance | ||||||
|
|
||||||
| ```go | ||||||
| config := self.VerificationConfig{ | ||||||
| Ofac: &[]bool{true}[0], // Require OFAC compliance | ||||||
| } | ||||||
| ``` | ||||||
|
|
||||||
| ### Combined Requirements | ||||||
|
|
||||||
| ```go | ||||||
| config := self.VerificationConfig{ | ||||||
| MinimumAge: &[]int{21}[0], | ||||||
| ExcludedCountries: []common.Country3LetterCode{common.USA}, | ||||||
| Ofac: &[]bool{true}[0], | ||||||
| } | ||||||
| ``` | ||||||
|
|
||||||
| ## Contributing | ||||||
|
|
||||||
| 1. Fork the repository | ||||||
| 2. Create your feature branch (`git checkout -b feature/amazing-feature`) | ||||||
| 3. Commit your changes (`git commit -m 'Add some amazing feature'`) | ||||||
| 4. Push to the branch (`git push origin feature/amazing-feature`) | ||||||
| 5. Open a Pull Request | ||||||
|
|
||||||
| ## License | ||||||
|
|
||||||
| This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. | ||||||
|
|
||||||
| ## Support | ||||||
|
|
||||||
| For support and questions: | ||||||
|
|
||||||
| - Create an issue in this repository | ||||||
| - Check the [Self Protocol documentation](https://docs.self.id) | ||||||
| - Join our [Discord community](https://discord.gg/worldcoin) | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Update Discord link to point to Self Protocol's community The Discord link currently points to Worldcoin's community. This should be updated to point to the Self Protocol's official Discord server. -- Join our [Discord community](https://discord.gg/worldcoin)
+- Join our [Discord community](https://discord.gg/self-protocol)📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Add nil check for getActionIdFunc
The
GetActionIdmethod could panic ifgetActionIdFuncis nil. Consider adding a defensive check.// GetActionId uses the custom function to generate action IDs func (store *InMemoryConfigStore) GetActionId(ctx context.Context, userIdentifier string, userDefinedData string) (string, error) { + if store.getActionIdFunc == nil { + return "", fmt.Errorf("getActionIdFunc is not configured") + } return store.getActionIdFunc(ctx, userIdentifier, userDefinedData) }📝 Committable suggestion
🤖 Prompt for AI Agents