menu-voucherlist #101
| @ -12,6 +12,7 @@ DB_SSLMODE=disable | |||||||
| DB_TIMEZONE=Africa/Nairobi | DB_TIMEZONE=Africa/Nairobi | ||||||
| 
 | 
 | ||||||
| #External API Calls | #External API Calls | ||||||
| CREATE_ACCOUNT_URL=https://custodial.sarafu.africa/api/account/create | CREATE_ACCOUNT_URL=http://localhost:5003/api/v2/account/create | ||||||
| TRACK_STATUS_URL=https://custodial.sarafu.africa/api/track/ | TRACK_STATUS_URL=https://custodial.sarafu.africa/api/track/ | ||||||
| BALANCE_URL=https://custodial.sarafu.africa/api/account/status/ | BALANCE_URL=https://custodial.sarafu.africa/api/account/status/ | ||||||
|  | TRACK_URL=http://localhost:5003/api/v2/account/status | ||||||
|  | |||||||
| @ -6,11 +6,13 @@ var ( | |||||||
| 	CreateAccountURL string | 	CreateAccountURL string | ||||||
| 	TrackStatusURL   string | 	TrackStatusURL   string | ||||||
| 	BalanceURL       string | 	BalanceURL       string | ||||||
|  |     TrackURL         string | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| // LoadConfig initializes the configuration values after environment variables are loaded.
 | // LoadConfig initializes the configuration values after environment variables are loaded.
 | ||||||
| func LoadConfig() { | func LoadConfig() { | ||||||
| 	CreateAccountURL = initializers.GetEnv("CREATE_ACCOUNT_URL", "https://custodial.sarafu.africa/api/account/create") | 	CreateAccountURL = initializers.GetEnv("CREATE_ACCOUNT_URL", "http://localhost:5003/api/v2/account/create") | ||||||
| 	TrackStatusURL = initializers.GetEnv("TRACK_STATUS_URL", "https://custodial.sarafu.africa/api/track/") | 	TrackStatusURL = initializers.GetEnv("TRACK_STATUS_URL", "https://custodial.sarafu.africa/api/track/") | ||||||
| 	BalanceURL = initializers.GetEnv("BALANCE_URL", "https://custodial.sarafu.africa/api/account/status/") | 	BalanceURL = initializers.GetEnv("BALANCE_URL", "https://custodial.sarafu.africa/api/account/status/") | ||||||
|  |     TrackURL = initializers.GetEnv("TRACK_URL", "http://localhost:5003/api/v2/account/status") | ||||||
| } | } | ||||||
|  | |||||||
							
								
								
									
										27
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										27
									
								
								go.mod
									
									
									
									
									
								
							| @ -1,29 +1,48 @@ | |||||||
| module git.grassecon.net/urdt/ussd | module git.grassecon.net/urdt/ussd | ||||||
| 
 | 
 | ||||||
| go 1.22.6 | go 1.23.0 | ||||||
|  | 
 | ||||||
|  | toolchain go1.23.2 | ||||||
| 
 | 
 | ||||||
| require ( | require ( | ||||||
| 	git.defalsify.org/vise.git v0.2.1-0.20241017112704-307fa6fcdc6b | 	git.defalsify.org/vise.git v0.2.1-0.20241017112704-307fa6fcdc6b | ||||||
| 	github.com/alecthomas/assert/v2 v2.2.2 | 	github.com/alecthomas/assert/v2 v2.2.2 | ||||||
| 	github.com/peteole/testdata-loader v0.3.0 | 	github.com/peteole/testdata-loader v0.3.0 | ||||||
| 	gopkg.in/leonelquinteros/gotext.v1 v1.3.1 | 	gopkg.in/leonelquinteros/gotext.v1 v1.3.1 | ||||||
|  | 
 | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| require github.com/joho/godotenv v1.5.1 // indirect | require github.com/joho/godotenv v1.5.1 | ||||||
|  | 
 | ||||||
|  | require ( | ||||||
|  | 	github.com/grassrootseconomics/eth-custodial v1.3.0-beta | ||||||
|  | 	github.com/jackc/pgpassfile v1.0.0 // indirect | ||||||
|  | 	github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect | ||||||
|  | 	github.com/jackc/pgx/v5 v5.7.1 // indirect | ||||||
|  | 	github.com/jackc/puddle/v2 v2.2.2 // indirect | ||||||
|  | 	github.com/kr/text v0.2.0 // indirect | ||||||
|  | 	github.com/rogpeppe/go-internal v1.13.1 // indirect | ||||||
|  | 	golang.org/x/crypto v0.27.0 // indirect | ||||||
|  | 	golang.org/x/sync v0.8.0 // indirect | ||||||
|  | 	golang.org/x/text v0.18.0 // indirect | ||||||
|  | ) | ||||||
| 
 | 
 | ||||||
| require ( | require ( | ||||||
| 	github.com/alecthomas/participle/v2 v2.0.0 // indirect | 	github.com/alecthomas/participle/v2 v2.0.0 // indirect | ||||||
| 	github.com/alecthomas/repr v0.2.0 // indirect | 	github.com/alecthomas/repr v0.2.0 // indirect | ||||||
| 	github.com/barbashov/iso639-3 v0.0.0-20211020172741-1f4ffb2d8d1c // indirect | 	github.com/barbashov/iso639-3 v0.0.0-20211020172741-1f4ffb2d8d1c // indirect | ||||||
| 	github.com/davecgh/go-spew v1.1.1 // indirect | 	github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect | ||||||
| 	github.com/fxamacker/cbor/v2 v2.4.0 // indirect | 	github.com/fxamacker/cbor/v2 v2.4.0 // indirect | ||||||
| 	github.com/gofrs/uuid v4.4.0+incompatible | 	github.com/gofrs/uuid v4.4.0+incompatible | ||||||
| 	github.com/graygnuorg/go-gdbm v0.0.0-20220711140707-71387d66dce4 // indirect | 	github.com/graygnuorg/go-gdbm v0.0.0-20220711140707-71387d66dce4 // indirect | ||||||
| 	github.com/hexops/gotextdiff v1.0.3 // indirect | 	github.com/hexops/gotextdiff v1.0.3 // indirect | ||||||
| 	github.com/mattn/kinako v0.0.0-20170717041458-332c0a7e205a // indirect | 	github.com/mattn/kinako v0.0.0-20170717041458-332c0a7e205a // indirect | ||||||
| 	github.com/pmezard/go-difflib v1.0.0 // indirect | 	github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect | ||||||
| 	github.com/stretchr/objx v0.5.2 // indirect | 	github.com/stretchr/objx v0.5.2 // indirect | ||||||
| 	github.com/stretchr/testify v1.9.0 | 	github.com/stretchr/testify v1.9.0 | ||||||
| 	github.com/x448/float16 v0.8.4 // indirect | 	github.com/x448/float16 v0.8.4 // indirect | ||||||
| 	gopkg.in/yaml.v3 v3.0.1 // indirect | 	gopkg.in/yaml.v3 v3.0.1 // indirect | ||||||
|  | 
 | ||||||
| ) | ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | |||||||
							
								
								
									
										44
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										44
									
								
								go.sum
									
									
									
									
									
								
							| @ -1,7 +1,3 @@ | |||||||
| git.defalsify.org/vise.git v0.1.0-rc.3.0.20240923162317-c20d557a3dbb h1:6P4kxihcwMjDKzvUFC6t2zGNb7MDW+l/ACGlSAN1N8Y= |  | ||||||
| git.defalsify.org/vise.git v0.1.0-rc.3.0.20240923162317-c20d557a3dbb/go.mod h1:JDguWmcoWBdsnpw7PUjVZAEpdC/ubBmjdUBy3tjP63M= |  | ||||||
| git.defalsify.org/vise.git v0.2.0 h1:X2ZgiGRq4C+9qOlDMP0b/oE5QHjVQNT4aEFZB88ST0Q= |  | ||||||
| git.defalsify.org/vise.git v0.2.0/go.mod h1:JDguWmcoWBdsnpw7PUjVZAEpdC/ubBmjdUBy3tjP63M= |  | ||||||
| git.defalsify.org/vise.git v0.2.1-0.20241017112704-307fa6fcdc6b h1:dxBplsIlzJHV+5EH+gzB+w08Blt7IJbb2jeRe1OEjLU= | git.defalsify.org/vise.git v0.2.1-0.20241017112704-307fa6fcdc6b h1:dxBplsIlzJHV+5EH+gzB+w08Blt7IJbb2jeRe1OEjLU= | ||||||
| git.defalsify.org/vise.git v0.2.1-0.20241017112704-307fa6fcdc6b/go.mod h1:jyBMe1qTYUz3mmuoC9JQ/TvFeW0vTanCUcPu3H8p4Ck= | git.defalsify.org/vise.git v0.2.1-0.20241017112704-307fa6fcdc6b/go.mod h1:jyBMe1qTYUz3mmuoC9JQ/TvFeW0vTanCUcPu3H8p4Ck= | ||||||
| github.com/alecthomas/assert/v2 v2.2.2 h1:Z/iVC0xZfWTaFNE6bA3z07T86hd45Xe2eLt6WVy2bbk= | github.com/alecthomas/assert/v2 v2.2.2 h1:Z/iVC0xZfWTaFNE6bA3z07T86hd45Xe2eLt6WVy2bbk= | ||||||
| @ -12,33 +8,65 @@ github.com/alecthomas/repr v0.2.0 h1:HAzS41CIzNW5syS8Mf9UwXhNH1J9aix/BvDRf1Ml2Yk | |||||||
| github.com/alecthomas/repr v0.2.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= | github.com/alecthomas/repr v0.2.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= | ||||||
| github.com/barbashov/iso639-3 v0.0.0-20211020172741-1f4ffb2d8d1c h1:H9Nm+I7Cg/YVPpEV1RzU3Wq2pjamPc/UtHDgItcb7lE= | github.com/barbashov/iso639-3 v0.0.0-20211020172741-1f4ffb2d8d1c h1:H9Nm+I7Cg/YVPpEV1RzU3Wq2pjamPc/UtHDgItcb7lE= | ||||||
| github.com/barbashov/iso639-3 v0.0.0-20211020172741-1f4ffb2d8d1c/go.mod h1:rGod7o6KPeJ+hyBpHfhi4v7blx9sf+QsHsA7KAsdN6U= | github.com/barbashov/iso639-3 v0.0.0-20211020172741-1f4ffb2d8d1c/go.mod h1:rGod7o6KPeJ+hyBpHfhi4v7blx9sf+QsHsA7KAsdN6U= | ||||||
| github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= | github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= | ||||||
| github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||||||
|  | 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/fxamacker/cbor/v2 v2.4.0 h1:ri0ArlOR+5XunOP8CRUowT0pSJOwhW098ZCUyskZD88= | github.com/fxamacker/cbor/v2 v2.4.0 h1:ri0ArlOR+5XunOP8CRUowT0pSJOwhW098ZCUyskZD88= | ||||||
| github.com/fxamacker/cbor/v2 v2.4.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo= | github.com/fxamacker/cbor/v2 v2.4.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo= | ||||||
| github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA= | github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA= | ||||||
| github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= | github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= | ||||||
|  | github.com/grassrootseconomics/eth-custodial v1.3.0-beta h1:twrMBhl89GqDUL9PlkzQxMP/6OST1BByrNDj+rqXDmU= | ||||||
|  | github.com/grassrootseconomics/eth-custodial v1.3.0-beta/go.mod h1:7uhRcdnJplX4t6GKCEFkbeDhhjlcaGJeJqevbcvGLZo= | ||||||
| github.com/graygnuorg/go-gdbm v0.0.0-20220711140707-71387d66dce4 h1:U4kkNYryi/qfbBF8gh7Vsbuz+cVmhf5kt6pE9bYYyLo= | github.com/graygnuorg/go-gdbm v0.0.0-20220711140707-71387d66dce4 h1:U4kkNYryi/qfbBF8gh7Vsbuz+cVmhf5kt6pE9bYYyLo= | ||||||
| github.com/graygnuorg/go-gdbm v0.0.0-20220711140707-71387d66dce4/go.mod h1:zpZDgZFzeq9s0MIeB1P50NIEWDFFHSFBohI/NbaTD/Y= | github.com/graygnuorg/go-gdbm v0.0.0-20220711140707-71387d66dce4/go.mod h1:zpZDgZFzeq9s0MIeB1P50NIEWDFFHSFBohI/NbaTD/Y= | ||||||
| github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= | github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= | ||||||
| github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= | github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= | ||||||
|  | github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= | ||||||
|  | github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= | ||||||
|  | github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo= | ||||||
|  | github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= | ||||||
|  | github.com/jackc/pgx/v5 v5.7.1 h1:x7SYsPBYDkHDksogeSmZZ5xzThcTgRz++I5E+ePFUcs= | ||||||
|  | github.com/jackc/pgx/v5 v5.7.1/go.mod h1:e7O26IywZZ+naJtWWos6i6fvWK+29etgITqrqHLfoZA= | ||||||
|  | github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo= | ||||||
|  | github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= | ||||||
| github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= | github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= | ||||||
| github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= | github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= | ||||||
|  | github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= | ||||||
|  | github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= | ||||||
|  | github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= | ||||||
|  | github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= | ||||||
| github.com/mattn/kinako v0.0.0-20170717041458-332c0a7e205a h1:0Q3H0YXzMHiciXtRcM+j0jiCe8WKPQHoRgQiRTnfcLY= | github.com/mattn/kinako v0.0.0-20170717041458-332c0a7e205a h1:0Q3H0YXzMHiciXtRcM+j0jiCe8WKPQHoRgQiRTnfcLY= | ||||||
| github.com/mattn/kinako v0.0.0-20170717041458-332c0a7e205a/go.mod h1:CdTTBOYzS5E4mWS1N8NWP6AHI19MP0A2B18n3hLzRMk= | github.com/mattn/kinako v0.0.0-20170717041458-332c0a7e205a/go.mod h1:CdTTBOYzS5E4mWS1N8NWP6AHI19MP0A2B18n3hLzRMk= | ||||||
|  | github.com/pashagolub/pgxmock/v4 v4.3.0 h1:DqT7fk0OCK6H0GvqtcMsLpv8cIwWqdxWgfZNLeHCb/s= | ||||||
|  | github.com/pashagolub/pgxmock/v4 v4.3.0/go.mod h1:9VoVHXwS3XR/yPtKGzwQvwZX1kzGB9sM8SviDcHDa3A= | ||||||
| github.com/peteole/testdata-loader v0.3.0 h1:8jckE9KcyNHgyv/VPoaljvKZE0Rqr8+dPVYH6rfNr9I= | github.com/peteole/testdata-loader v0.3.0 h1:8jckE9KcyNHgyv/VPoaljvKZE0Rqr8+dPVYH6rfNr9I= | ||||||
| github.com/peteole/testdata-loader v0.3.0/go.mod h1:Mt0ZbRtb56u8SLJpNP+BnQbENljMorYBpqlvt3cS83U= | github.com/peteole/testdata-loader v0.3.0/go.mod h1:Mt0ZbRtb56u8SLJpNP+BnQbENljMorYBpqlvt3cS83U= | ||||||
| github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= |  | ||||||
| github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | ||||||
|  | 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/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= | ||||||
|  | github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= | ||||||
|  | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | ||||||
| github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= | github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= | ||||||
| github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= | github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= | ||||||
|  | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= | ||||||
|  | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | ||||||
| github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= | github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= | ||||||
| github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= | github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= | ||||||
| github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= | github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= | ||||||
| github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= | github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= | ||||||
| gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= | golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= | ||||||
|  | golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= | ||||||
|  | golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= | ||||||
|  | golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= | ||||||
|  | golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= | ||||||
|  | golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= | ||||||
| gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||||||
|  | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= | ||||||
|  | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= | ||||||
| gopkg.in/leonelquinteros/gotext.v1 v1.3.1 h1:8d9/fdTG0kn/B7NNGV1BsEyvektXFAbkMsTZS2sFSCc= | gopkg.in/leonelquinteros/gotext.v1 v1.3.1 h1:8d9/fdTG0kn/B7NNGV1BsEyvektXFAbkMsTZS2sFSCc= | ||||||
| gopkg.in/leonelquinteros/gotext.v1 v1.3.1/go.mod h1:X1WlGDeAFIYsW6GjgMm4VwUwZ2XjI7Zan2InxSUQWrU= | gopkg.in/leonelquinteros/gotext.v1 v1.3.1/go.mod h1:X1WlGDeAFIYsW6GjgMm4VwUwZ2XjI7Zan2InxSUQWrU= | ||||||
|  | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= | ||||||
| gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= | ||||||
| gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= | ||||||
|  | |||||||
| @ -1,7 +1,10 @@ | |||||||
| package server | package server | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
|  | 	"context" | ||||||
| 	"encoding/json" | 	"encoding/json" | ||||||
|  | 	"errors" | ||||||
|  | 	"fmt" | ||||||
| 	"io" | 	"io" | ||||||
| 	"net/http" | 	"net/http" | ||||||
| 	"os" | 	"os" | ||||||
| @ -9,12 +12,19 @@ import ( | |||||||
| 
 | 
 | ||||||
| 	"git.grassecon.net/urdt/ussd/config" | 	"git.grassecon.net/urdt/ussd/config" | ||||||
| 	"git.grassecon.net/urdt/ussd/internal/models" | 	"git.grassecon.net/urdt/ussd/internal/models" | ||||||
|  | 	"github.com/grassrootseconomics/eth-custodial/pkg/api" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | var ( | ||||||
|  | 	okResponse  api.OKResponse | ||||||
|  | 	errResponse api.ErrResponse | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| type AccountServiceInterface interface { | type AccountServiceInterface interface { | ||||||
| 	CheckBalance(publicKey string) (*models.BalanceResponse, error) | 	CheckBalance(ctx context.Context, publicKey string) (*models.BalanceResponse, error) | ||||||
| 	CreateAccount() (*models.AccountResponse, error) | 	CreateAccount(ctx context.Context) (*api.OKResponse, error) | ||||||
| 	CheckAccountStatus(trackingId string) (*models.TrackStatusResponse, error) | 	CheckAccountStatus(ctx context.Context, trackingId string) (*models.TrackStatusResponse, error) | ||||||
|  | 	TrackAccountStatus(ctx context.Context, publicKey string) (*api.OKResponse, error) | ||||||
| 	FetchVouchers(publicKey string) (*models.VoucherHoldingResponse, error) | 	FetchVouchers(publicKey string) (*models.VoucherHoldingResponse, error) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -24,8 +34,6 @@ type AccountService struct { | |||||||
| type TestAccountService struct { | type TestAccountService struct { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // CheckAccountStatus retrieves the status of an account transaction based on the provided tracking ID.
 |  | ||||||
| //
 |  | ||||||
| // Parameters:
 | // Parameters:
 | ||||||
| //   - trackingId: A unique identifier for the account.This should be obtained from a previous call to
 | //   - trackingId: A unique identifier for the account.This should be obtained from a previous call to
 | ||||||
| //     CreateAccount or a similar function that returns an AccountResponse. The `trackingId` field in the
 | //     CreateAccount or a similar function that returns an AccountResponse. The `trackingId` field in the
 | ||||||
| @ -34,9 +42,9 @@ type TestAccountService struct { | |||||||
| // Returns:
 | // Returns:
 | ||||||
| //   - string: The status of the transaction as a string. If there is an error during the request or processing, this will be an empty string.
 | //   - string: The status of the transaction as a string. If there is an error during the request or processing, this will be an empty string.
 | ||||||
| //   - error: An error if any occurred during the HTTP request, reading the response, or unmarshalling the JSON data.
 | //   - error: An error if any occurred during the HTTP request, reading the response, or unmarshalling the JSON data.
 | ||||||
| //     If no error occurs, this will be nil.
 | //     If no error occurs, this will be nil
 | ||||||
| func (as *AccountService) CheckAccountStatus(trackingId string) (*models.TrackStatusResponse, error) { | func (as *AccountService) CheckAccountStatus(ctx context.Context, trackingId string) (*models.TrackStatusResponse, error) { | ||||||
| 	resp, err := http.Get(config.TrackStatusURL + trackingId) | 	resp, err := http.Get(config.BalanceURL + trackingId) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
| @ -46,18 +54,61 @@ func (as *AccountService) CheckAccountStatus(trackingId string) (*models.TrackSt | |||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
| 	var trackResp models.TrackStatusResponse | 	var trackResp models.TrackStatusResponse | ||||||
| 	err = json.Unmarshal(body, &trackResp) | 	err = json.Unmarshal(body, &trackResp) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
| 	return &trackResp, nil | 	return &trackResp, nil | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (as *AccountService) TrackAccountStatus(ctx context.Context, publicKey string) (*api.OKResponse, error) { | ||||||
|  | 	var err error | ||||||
|  | 	// Construct the URL with the path parameter
 | ||||||
|  | 	url := fmt.Sprintf("%s/%s", config.TrackURL, publicKey) | ||||||
|  | 	req, err := http.NewRequest("GET", url, nil) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	req.Header.Set("Content-Type", "application/json") | ||||||
|  | 	req.Header.Set("X-GE-KEY", "xd") | ||||||
|  | 
 | ||||||
|  | 	resp, err := http.DefaultClient.Do(req) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	defer resp.Body.Close() | ||||||
|  | 
 | ||||||
|  | 	body, err := io.ReadAll(resp.Body) | ||||||
|  | 	if err != nil { | ||||||
|  | 		errResponse.Description = err.Error() | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	if resp.StatusCode >= http.StatusBadRequest { | ||||||
|  | 		err := json.Unmarshal([]byte(body), &errResponse) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return nil, err | ||||||
|  | 		} | ||||||
|  | 		return nil, errors.New(errResponse.Description) | ||||||
|  | 	} | ||||||
|  | 	err = json.Unmarshal([]byte(body), &okResponse) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	if len(okResponse.Result) == 0 { | ||||||
|  | 		return nil, errors.New("Empty api result") | ||||||
|  | 	} | ||||||
|  | 	return &okResponse, nil | ||||||
|  | 
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // CheckBalance retrieves the balance for a given public key from the custodial balance API endpoint.
 | // CheckBalance retrieves the balance for a given public key from the custodial balance API endpoint.
 | ||||||
| // Parameters:
 | // Parameters:
 | ||||||
| //   - publicKey: The public key associated with the account whose balance needs to be checked.
 | //   - publicKey: The public key associated with the account whose balance needs to be checked.
 | ||||||
| func (as *AccountService) CheckBalance(publicKey string) (*models.BalanceResponse, error) { | func (as *AccountService) CheckBalance(ctx context.Context, publicKey string) (*models.BalanceResponse, error) { | ||||||
| 	resp, err := http.Get(config.BalanceURL + publicKey) | 	resp, err := http.Get(config.BalanceURL + publicKey) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| @ -81,22 +132,43 @@ func (as *AccountService) CheckBalance(publicKey string) (*models.BalanceRespons | |||||||
| //     If there is an error during the request or processing, this will be nil.
 | //     If there is an error during the request or processing, this will be nil.
 | ||||||
| //   - error: An error if any occurred during the HTTP request, reading the response, or unmarshalling the JSON data.
 | //   - error: An error if any occurred during the HTTP request, reading the response, or unmarshalling the JSON data.
 | ||||||
| //     If no error occurs, this will be nil.
 | //     If no error occurs, this will be nil.
 | ||||||
| func (as *AccountService) CreateAccount() (*models.AccountResponse, error) { | func (as *AccountService) CreateAccount(ctx context.Context) (*api.OKResponse, error) { | ||||||
| 	resp, err := http.Post(config.CreateAccountURL, "application/json", nil) | 	var err error | ||||||
|  | 
 | ||||||
|  | 	// Create a new request
 | ||||||
|  | 	req, err := http.NewRequest("POST", config.CreateAccountURL, nil) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
|  | 	req.Header.Set("Content-Type", "application/json") | ||||||
|  | 	req.Header.Set("X-GE-KEY", "xd") | ||||||
|  | 
 | ||||||
|  | 	resp, err := http.DefaultClient.Do(req) | ||||||
|  | 	if err != nil { | ||||||
|  | 		errResponse.Description = err.Error() | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
| 	defer resp.Body.Close() | 	defer resp.Body.Close() | ||||||
|  | 
 | ||||||
| 	body, err := io.ReadAll(resp.Body) | 	body, err := io.ReadAll(resp.Body) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
| 	var accountResp models.AccountResponse | 	if resp.StatusCode >= http.StatusBadRequest { | ||||||
| 	err = json.Unmarshal(body, &accountResp) | 		err := json.Unmarshal([]byte(body), &errResponse) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return nil, err | ||||||
|  | 		} | ||||||
|  | 		return nil, errors.New(errResponse.Description) | ||||||
|  | 	} | ||||||
|  | 	err = json.Unmarshal([]byte(body), &okResponse) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
| 	return &accountResp, nil | 	if len(okResponse.Result) == 0 { | ||||||
|  | 		return nil, errors.New("Empty api result") | ||||||
|  | 	} | ||||||
|  | 	return &okResponse, nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // FetchVouchers retrieves the token holdings for a given public key from the custodial holdings API endpoint
 | // FetchVouchers retrieves the token holdings for a given public key from the custodial holdings API endpoint
 | ||||||
| @ -116,22 +188,16 @@ func (as *AccountService) FetchVouchers(publicKey string) (*models.VoucherHoldin | |||||||
| 	return &holdings, nil | 	return &holdings, nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (tas *TestAccountService) CreateAccount() (*models.AccountResponse, error) { | func (tas *TestAccountService) CreateAccount(ctx context.Context) (*api.OKResponse, error) { | ||||||
| 	return &models.AccountResponse{ | 	return &api.OKResponse{ | ||||||
| 		Ok: true, | 		Ok:          true, | ||||||
| 		Result: struct { | 		Description: "Account creation request received successfully", | ||||||
| 			CustodialId json.Number `json:"custodialId"` | 		Result:      map[string]any{"publicKey": "0x48ADca309b5085852207FAaf2816eD72B52F527C", "trackingId": "28ebe84d-b925-472c-87ae-bbdfa1fb97be"}, | ||||||
| 			PublicKey   string      `json:"publicKey"` |  | ||||||
| 			TrackingId  string      `json:"trackingId"` |  | ||||||
| 		}{ |  | ||||||
| 			CustodialId: json.Number("182"), |  | ||||||
| 			PublicKey:   "0x48ADca309b5085852207FAaf2816eD72B52F527C", |  | ||||||
| 			TrackingId:  "28ebe84d-b925-472c-87ae-bbdfa1fb97be", |  | ||||||
| 		}, |  | ||||||
| 	}, nil | 	}, nil | ||||||
|  | 
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (tas *TestAccountService) CheckBalance(publicKey string) (*models.BalanceResponse, error) { | func (tas *TestAccountService) CheckBalance(ctx context.Context, publicKey string) (*models.BalanceResponse, error) { | ||||||
| 	balanceResponse := &models.BalanceResponse{ | 	balanceResponse := &models.BalanceResponse{ | ||||||
| 		Ok: true, | 		Ok: true, | ||||||
| 		Result: struct { | 		Result: struct { | ||||||
| @ -142,11 +208,20 @@ func (tas *TestAccountService) CheckBalance(publicKey string) (*models.BalanceRe | |||||||
| 			Nonce:   json.Number("0"), | 			Nonce:   json.Number("0"), | ||||||
| 		}, | 		}, | ||||||
| 	} | 	} | ||||||
| 
 |  | ||||||
| 	return balanceResponse, nil | 	return balanceResponse, nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (tas *TestAccountService) CheckAccountStatus(trackingId string) (*models.TrackStatusResponse, error) { | func (tas *TestAccountService) TrackAccountStatus(ctx context.Context, publicKey string) (*api.OKResponse, error) { | ||||||
|  | 	return &api.OKResponse{ | ||||||
|  | 		Ok:          true, | ||||||
|  | 		Description: "Account creation succeeded", | ||||||
|  | 		Result: map[string]any{ | ||||||
|  | 			"active": true, | ||||||
|  | 		}, | ||||||
|  | 	}, nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (tas *TestAccountService) CheckAccountStatus(ctx context.Context, trackingId string) (*models.TrackStatusResponse, error) { | ||||||
| 	trackResponse := &models.TrackStatusResponse{ | 	trackResponse := &models.TrackStatusResponse{ | ||||||
| 		Ok: true, | 		Ok: true, | ||||||
| 		Result: struct { | 		Result: struct { | ||||||
|  | |||||||
| @ -10,6 +10,7 @@ import ( | |||||||
| 	"strings" | 	"strings" | ||||||
| 
 | 
 | ||||||
| 	"git.defalsify.org/vise.git/asm" | 	"git.defalsify.org/vise.git/asm" | ||||||
|  | 	"github.com/grassrootseconomics/eth-custodial/pkg/api" | ||||||
| 
 | 
 | ||||||
| 	"git.defalsify.org/vise.git/cache" | 	"git.defalsify.org/vise.git/cache" | ||||||
| 	"git.defalsify.org/vise.git/db" | 	"git.defalsify.org/vise.git/db" | ||||||
| @ -29,6 +30,8 @@ var ( | |||||||
| 	logg           = logging.NewVanilla().WithDomain("ussdmenuhandler") | 	logg           = logging.NewVanilla().WithDomain("ussdmenuhandler") | ||||||
| 	scriptDir      = path.Join("services", "registration") | 	scriptDir      = path.Join("services", "registration") | ||||||
| 	translationDir = path.Join(scriptDir, "locale") | 	translationDir = path.Join(scriptDir, "locale") | ||||||
|  | 	okResponse     *api.OKResponse | ||||||
|  | 	errResponse    *api.ErrResponse | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| // FlagManager handles centralized flag management
 | // FlagManager handles centralized flag management
 | ||||||
| @ -138,13 +141,18 @@ func (h *Handlers) SetLanguage(ctx context.Context, sym string, input []byte) (r | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (h *Handlers) createAccountNoExist(ctx context.Context, sessionId string, res *resource.Result) error { | func (h *Handlers) createAccountNoExist(ctx context.Context, sessionId string, res *resource.Result) error { | ||||||
| 	accountResp, err := h.accountService.CreateAccount() | 	flag_account_created, _ := h.flagManager.GetFlag("flag_account_created") | ||||||
| 	data := map[utils.DataTyp]string{ | 	okResponse, err := h.accountService.CreateAccount(ctx) | ||||||
| 		utils.DATA_TRACKING_ID:  accountResp.Result.TrackingId, | 	if err != nil { | ||||||
| 		utils.DATA_PUBLIC_KEY:   accountResp.Result.PublicKey, | 		return err | ||||||
| 		utils.DATA_CUSTODIAL_ID: accountResp.Result.CustodialId.String(), |  | ||||||
| 	} | 	} | ||||||
|  | 	trackingId := okResponse.Result["trackingId"].(string) | ||||||
|  | 	publicKey := okResponse.Result["publicKey"].(string) | ||||||
| 
 | 
 | ||||||
|  | 	data := map[utils.DataTyp]string{ | ||||||
|  | 		utils.DATA_TRACKING_ID: trackingId, | ||||||
|  | 		utils.DATA_PUBLIC_KEY:  publicKey, | ||||||
|  | 	} | ||||||
| 	for key, value := range data { | 	for key, value := range data { | ||||||
| 		store := h.userdataStore | 		store := h.userdataStore | ||||||
| 		err := store.WriteEntry(ctx, sessionId, key, []byte(value)) | 		err := store.WriteEntry(ctx, sessionId, key, []byte(value)) | ||||||
| @ -152,9 +160,8 @@ func (h *Handlers) createAccountNoExist(ctx context.Context, sessionId string, r | |||||||
| 			return err | 			return err | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	flag_account_created, _ := h.flagManager.GetFlag("flag_account_created") |  | ||||||
| 	res.FlagSet = append(res.FlagSet, flag_account_created) | 	res.FlagSet = append(res.FlagSet, flag_account_created) | ||||||
| 	return err | 	return nil | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -355,7 +362,6 @@ func (h *Handlers) SaveYob(ctx context.Context, sym string, input []byte) (resou | |||||||
| 	if !ok { | 	if !ok { | ||||||
| 		return res, fmt.Errorf("missing session") | 		return res, fmt.Errorf("missing session") | ||||||
| 	} | 	} | ||||||
| 
 |  | ||||||
| 	if len(input) == 4 { | 	if len(input) == 4 { | ||||||
| 		yob := string(input) | 		yob := string(input) | ||||||
| 		store := h.userdataStore | 		store := h.userdataStore | ||||||
| @ -398,7 +404,6 @@ func (h *Handlers) SaveGender(ctx context.Context, sym string, input []byte) (re | |||||||
| 	if !ok { | 	if !ok { | ||||||
| 		return res, fmt.Errorf("missing session") | 		return res, fmt.Errorf("missing session") | ||||||
| 	} | 	} | ||||||
| 
 |  | ||||||
| 	gender := strings.Split(symbol, "_")[1] | 	gender := strings.Split(symbol, "_")[1] | ||||||
| 	store := h.userdataStore | 	store := h.userdataStore | ||||||
| 	err = store.WriteEntry(ctx, sessionId, utils.DATA_GENDER, []byte(gender)) | 	err = store.WriteEntry(ctx, sessionId, utils.DATA_GENDER, []byte(gender)) | ||||||
| @ -417,7 +422,6 @@ func (h *Handlers) SaveOfferings(ctx context.Context, sym string, input []byte) | |||||||
| 	if !ok { | 	if !ok { | ||||||
| 		return res, fmt.Errorf("missing session") | 		return res, fmt.Errorf("missing session") | ||||||
| 	} | 	} | ||||||
| 
 |  | ||||||
| 	if len(input) > 0 { | 	if len(input) > 0 { | ||||||
| 		offerings := string(input) | 		offerings := string(input) | ||||||
| 		store := h.userdataStore | 		store := h.userdataStore | ||||||
| @ -443,7 +447,6 @@ func (h *Handlers) ResetAllowUpdate(ctx context.Context, sym string, input []byt | |||||||
| // ResetAccountAuthorized resets the account authorization flag after a successful PIN entry.
 | // ResetAccountAuthorized resets the account authorization flag after a successful PIN entry.
 | ||||||
| func (h *Handlers) ResetAccountAuthorized(ctx context.Context, sym string, input []byte) (resource.Result, error) { | func (h *Handlers) ResetAccountAuthorized(ctx context.Context, sym string, input []byte) (resource.Result, error) { | ||||||
| 	var res resource.Result | 	var res resource.Result | ||||||
| 
 |  | ||||||
| 	flag_account_authorized, _ := h.flagManager.GetFlag("flag_account_authorized") | 	flag_account_authorized, _ := h.flagManager.GetFlag("flag_account_authorized") | ||||||
| 
 | 
 | ||||||
| 	res.FlagReset = append(res.FlagReset, flag_account_authorized) | 	res.FlagReset = append(res.FlagReset, flag_account_authorized) | ||||||
| @ -453,12 +456,10 @@ func (h *Handlers) ResetAccountAuthorized(ctx context.Context, sym string, input | |||||||
| // CheckIdentifier retrieves the PublicKey from the JSON data file.
 | // CheckIdentifier retrieves the PublicKey from the JSON data file.
 | ||||||
| func (h *Handlers) CheckIdentifier(ctx context.Context, sym string, input []byte) (resource.Result, error) { | func (h *Handlers) CheckIdentifier(ctx context.Context, sym string, input []byte) (resource.Result, error) { | ||||||
| 	var res resource.Result | 	var res resource.Result | ||||||
| 
 |  | ||||||
| 	sessionId, ok := ctx.Value("SessionId").(string) | 	sessionId, ok := ctx.Value("SessionId").(string) | ||||||
| 	if !ok { | 	if !ok { | ||||||
| 		return res, fmt.Errorf("missing session") | 		return res, fmt.Errorf("missing session") | ||||||
| 	} | 	} | ||||||
| 
 |  | ||||||
| 	store := h.userdataStore | 	store := h.userdataStore | ||||||
| 	publicKey, _ := store.ReadEntry(ctx, sessionId, utils.DATA_PUBLIC_KEY) | 	publicKey, _ := store.ReadEntry(ctx, sessionId, utils.DATA_PUBLIC_KEY) | ||||||
| 
 | 
 | ||||||
| @ -472,12 +473,10 @@ func (h *Handlers) CheckIdentifier(ctx context.Context, sym string, input []byte | |||||||
| func (h *Handlers) Authorize(ctx context.Context, sym string, input []byte) (resource.Result, error) { | func (h *Handlers) Authorize(ctx context.Context, sym string, input []byte) (resource.Result, error) { | ||||||
| 	var res resource.Result | 	var res resource.Result | ||||||
| 	var err error | 	var err error | ||||||
| 
 |  | ||||||
| 	sessionId, ok := ctx.Value("SessionId").(string) | 	sessionId, ok := ctx.Value("SessionId").(string) | ||||||
| 	if !ok { | 	if !ok { | ||||||
| 		return res, fmt.Errorf("missing session") | 		return res, fmt.Errorf("missing session") | ||||||
| 	} | 	} | ||||||
| 
 |  | ||||||
| 	flag_incorrect_pin, _ := h.flagManager.GetFlag("flag_incorrect_pin") | 	flag_incorrect_pin, _ := h.flagManager.GetFlag("flag_incorrect_pin") | ||||||
| 	flag_account_authorized, _ := h.flagManager.GetFlag("flag_account_authorized") | 	flag_account_authorized, _ := h.flagManager.GetFlag("flag_account_authorized") | ||||||
| 	flag_allow_update, _ := h.flagManager.GetFlag("flag_allow_update") | 	flag_allow_update, _ := h.flagManager.GetFlag("flag_allow_update") | ||||||
| @ -529,28 +528,21 @@ func (h *Handlers) CheckAccountStatus(ctx context.Context, sym string, input []b | |||||||
| 		return res, fmt.Errorf("missing session") | 		return res, fmt.Errorf("missing session") | ||||||
| 	} | 	} | ||||||
| 	store := h.userdataStore | 	store := h.userdataStore | ||||||
| 	trackingId, err := store.ReadEntry(ctx, sessionId, utils.DATA_TRACKING_ID) | 	publicKey, err := store.ReadEntry(ctx, sessionId, utils.DATA_PUBLIC_KEY) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return res, err | 		return res, err | ||||||
| 	} | 	} | ||||||
| 
 | 	okResponse, err = h.accountService.TrackAccountStatus(ctx, string(publicKey)) | ||||||
| 	accountStatus, err := h.accountService.CheckAccountStatus(string(trackingId)) |  | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		fmt.Println("Error checking account status:", err) |  | ||||||
| 		return res, err |  | ||||||
| 	} |  | ||||||
| 	if !accountStatus.Ok { |  | ||||||
| 		res.FlagSet = append(res.FlagSet, flag_api_error) | 		res.FlagSet = append(res.FlagSet, flag_api_error) | ||||||
| 		return res, err | 		return res, err | ||||||
| 	} | 	} | ||||||
| 	res.FlagReset = append(res.FlagReset, flag_api_error) | 	res.FlagReset = append(res.FlagReset, flag_api_error) | ||||||
| 	status := accountStatus.Result.Transaction.Status | 	isActive := okResponse.Result["active"].(bool) | ||||||
| 
 | 	if !ok { | ||||||
| 	err = store.WriteEntry(ctx, sessionId, utils.DATA_ACCOUNT_STATUS, []byte(status)) | 		return res, err | ||||||
| 	if err != nil { |  | ||||||
| 		return res, nil |  | ||||||
| 	} | 	} | ||||||
| 	if accountStatus.Result.Transaction.Status == "SUCCESS" { | 	if isActive { | ||||||
| 		res.FlagSet = append(res.FlagSet, flag_account_success) | 		res.FlagSet = append(res.FlagSet, flag_account_success) | ||||||
| 		res.FlagReset = append(res.FlagReset, flag_account_pending) | 		res.FlagReset = append(res.FlagReset, flag_account_pending) | ||||||
| 	} else { | 	} else { | ||||||
| @ -680,7 +672,7 @@ func (h *Handlers) FetchCustodialBalances(ctx context.Context, sym string, input | |||||||
| 		return res, err | 		return res, err | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	balanceResponse, err := h.accountService.CheckBalance(string(publicKey)) | 	balanceResponse, err := h.accountService.CheckBalance(ctx, string(publicKey)) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return res, nil | 		return res, nil | ||||||
| 	} | 	} | ||||||
|  | |||||||
| @ -20,6 +20,7 @@ import ( | |||||||
| 	"git.grassecon.net/urdt/ussd/internal/models" | 	"git.grassecon.net/urdt/ussd/internal/models" | ||||||
| 	"git.grassecon.net/urdt/ussd/internal/utils" | 	"git.grassecon.net/urdt/ussd/internal/utils" | ||||||
| 	"github.com/alecthomas/assert/v2" | 	"github.com/alecthomas/assert/v2" | ||||||
|  | 	"github.com/grassrootseconomics/eth-custodial/pkg/api" | ||||||
| 	testdataloader "github.com/peteole/testdata-loader" | 	testdataloader "github.com/peteole/testdata-loader" | ||||||
| 	"github.com/stretchr/testify/require" | 	"github.com/stretchr/testify/require" | ||||||
| ) | ) | ||||||
| @ -72,68 +73,74 @@ func TestCreateAccount(t *testing.T) { | |||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		t.Logf(err.Error()) | 		t.Logf(err.Error()) | ||||||
| 	} | 	} | ||||||
| 
 |  | ||||||
| 	// Create required mocks
 | 	// Create required mocks
 | ||||||
| 	mockDataStore := new(mocks.MockUserDataStore) | 	flag_account_created, err := fm.GetFlag("flag_account_created") | ||||||
| 	mockCreateAccountService := new(mocks.MockAccountService) |  | ||||||
| 	expectedResult := resource.Result{} |  | ||||||
| 	accountCreatedFlag, err := fm.GetFlag("flag_account_created") |  | ||||||
| 
 |  | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		t.Logf(err.Error()) | 		t.Logf(err.Error()) | ||||||
| 	} | 	} | ||||||
| 	expectedResult.FlagSet = append(expectedResult.FlagSet, accountCreatedFlag) |  | ||||||
| 
 |  | ||||||
| 	// Define session ID and mock data
 | 	// Define session ID and mock data
 | ||||||
| 	sessionId := "session123" | 	sessionId := "session123" | ||||||
| 	typ := utils.DATA_ACCOUNT_CREATED | 	notFoundErr := db.ErrNotFound{} | ||||||
| 	fakeError := db.ErrNotFound{} |  | ||||||
| 	// Create context with session ID
 |  | ||||||
| 	ctx := context.WithValue(context.Background(), "SessionId", sessionId) | 	ctx := context.WithValue(context.Background(), "SessionId", sessionId) | ||||||
| 
 | 
 | ||||||
| 	// Define expected interactions with the mock
 | 	tests := []struct { | ||||||
| 	mockDataStore.On("ReadEntry", ctx, sessionId, typ).Return([]byte("123"), fakeError) | 		name           string | ||||||
| 	expectedAccountResp := &models.AccountResponse{ | 		serverResponse *api.OKResponse | ||||||
| 		Ok: true, | 		expectedResult resource.Result | ||||||
| 		Result: struct { | 	}{ | ||||||
| 			CustodialId json.Number `json:"custodialId"` | 		{ | ||||||
| 			PublicKey   string      `json:"publicKey"` | 			name: "Test account creation success", | ||||||
| 			TrackingId  string      `json:"trackingId"` | 			serverResponse: &api.OKResponse{ | ||||||
| 		}{ | 				Ok:          true, | ||||||
| 			CustodialId: "12", | 				Description: "Account creation successed", | ||||||
| 			PublicKey:   "0x8E0XSCSVA", | 				Result: map[string]any{ | ||||||
| 			TrackingId:  "d95a7e83-196c-4fd0-866fSGAGA", | 					"trackingId": "1234567890", | ||||||
|  | 					"publicKey":  "1235QERYU", | ||||||
|  | 				}, | ||||||
|  | 			}, | ||||||
|  | 			expectedResult: resource.Result{ | ||||||
|  | 				FlagSet: []uint32{flag_account_created}, | ||||||
|  | 			}, | ||||||
| 		}, | 		}, | ||||||
| 	} | 	} | ||||||
| 	mockCreateAccountService.On("CreateAccount").Return(expectedAccountResp, nil) | 	for _, tt := range tests { | ||||||
| 	data := map[utils.DataTyp]string{ | 		t.Run(tt.name, func(t *testing.T) { | ||||||
| 		utils.DATA_TRACKING_ID:  expectedAccountResp.Result.TrackingId, | 
 | ||||||
| 		utils.DATA_PUBLIC_KEY:   expectedAccountResp.Result.PublicKey, | 			mockDataStore := new(mocks.MockUserDataStore) | ||||||
| 		utils.DATA_CUSTODIAL_ID: expectedAccountResp.Result.CustodialId.String(), | 			mockCreateAccountService := new(mocks.MockAccountService) | ||||||
|  | 
 | ||||||
|  | 			// Create a Handlers instance with the mock data store
 | ||||||
|  | 			h := &Handlers{ | ||||||
|  | 				userdataStore:  mockDataStore, | ||||||
|  | 				accountService: mockCreateAccountService, | ||||||
|  | 				flagManager:    fm.parser, | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			data := map[utils.DataTyp]string{ | ||||||
|  | 				utils.DATA_TRACKING_ID: tt.serverResponse.Result["trackingId"].(string), | ||||||
|  | 				utils.DATA_PUBLIC_KEY:  tt.serverResponse.Result["publicKey"].(string), | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_ACCOUNT_CREATED).Return([]byte(""), notFoundErr) | ||||||
|  | 			mockCreateAccountService.On("CreateAccount").Return(tt.serverResponse, nil) | ||||||
|  | 
 | ||||||
|  | 			for key, value := range data { | ||||||
|  | 				mockDataStore.On("WriteEntry", ctx, sessionId, key, []byte(value)).Return(nil) | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			// Call the method you want to test
 | ||||||
|  | 			res, err := h.CreateAccount(ctx, "create_account", []byte("some-input")) | ||||||
|  | 
 | ||||||
|  | 			// Assert that no errors occurred
 | ||||||
|  | 			assert.NoError(t, err) | ||||||
|  | 
 | ||||||
|  | 			// Assert that the account created flag has been set to the result
 | ||||||
|  | 			assert.Equal(t, res, tt.expectedResult, "Expected result should be equal to the actual result") | ||||||
|  | 
 | ||||||
|  | 			// Assert that expectations were met
 | ||||||
|  | 			mockDataStore.AssertExpectations(t) | ||||||
|  | 		}) | ||||||
| 	} | 	} | ||||||
| 
 |  | ||||||
| 	for key, value := range data { |  | ||||||
| 		mockDataStore.On("WriteEntry", ctx, sessionId, key, []byte(value)).Return(nil) |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	// Create a Handlers instance with the mock data store
 |  | ||||||
| 	h := &Handlers{ |  | ||||||
| 		userdataStore:  mockDataStore, |  | ||||||
| 		accountService: mockCreateAccountService, |  | ||||||
| 		flagManager:    fm.parser, |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	// Call the method you want to test
 |  | ||||||
| 	res, err := h.CreateAccount(ctx, "create_account", []byte("some-input")) |  | ||||||
| 
 |  | ||||||
| 	// Assert that no errors occurred
 |  | ||||||
| 	assert.NoError(t, err) |  | ||||||
| 
 |  | ||||||
| 	//Assert that the account created flag has been set to the result
 |  | ||||||
| 	assert.Equal(t, res, expectedResult, "Expected result should be equal to the actual result") |  | ||||||
| 
 |  | ||||||
| 	// Assert that expectations were met
 |  | ||||||
| 	mockDataStore.AssertExpectations(t) |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func TestWithPersister(t *testing.T) { | func TestWithPersister(t *testing.T) { | ||||||
| @ -1037,12 +1044,20 @@ func TestCheckAccountStatus(t *testing.T) { | |||||||
| 	tests := []struct { | 	tests := []struct { | ||||||
| 		name           string | 		name           string | ||||||
| 		input          []byte | 		input          []byte | ||||||
|  | 		serverResponse *api.OKResponse | ||||||
| 		response       *models.TrackStatusResponse | 		response       *models.TrackStatusResponse | ||||||
| 		expectedResult resource.Result | 		expectedResult resource.Result | ||||||
| 	}{ | 	}{ | ||||||
| 		{ | 		{ | ||||||
| 			name:  "Test when account status is Success", | 			name:  "Test when account is on the Sarafu network", | ||||||
| 			input: []byte("TrackingId1234"), | 			input: []byte("TrackingId1234"), | ||||||
|  | 			serverResponse: &api.OKResponse{ | ||||||
|  | 				Ok:          true, | ||||||
|  | 				Description: "Account creation succeeded", | ||||||
|  | 				Result: map[string]any{ | ||||||
|  | 					"active": true, | ||||||
|  | 				}, | ||||||
|  | 			}, | ||||||
| 			response: &models.TrackStatusResponse{ | 			response: &models.TrackStatusResponse{ | ||||||
| 				Ok: true, | 				Ok: true, | ||||||
| 				Result: struct { | 				Result: struct { | ||||||
| @ -1069,17 +1084,7 @@ func TestCheckAccountStatus(t *testing.T) { | |||||||
| 			}, | 			}, | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			name:  "Test when fetching  account status is not  Success", | 			name:  "Test when the account is not  yet on the sarafu network", | ||||||
| 			input: []byte("TrackingId1234"), |  | ||||||
| 			response: &models.TrackStatusResponse{ |  | ||||||
| 				Ok: false, |  | ||||||
| 			}, |  | ||||||
| 			expectedResult: resource.Result{ |  | ||||||
| 				FlagSet: []uint32{flag_api_error}, |  | ||||||
| 			}, |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			name:  "Test when checking account status api call is a SUCCESS but an account is not yet ready", |  | ||||||
| 			input: []byte("TrackingId1234"), | 			input: []byte("TrackingId1234"), | ||||||
| 			response: &models.TrackStatusResponse{ | 			response: &models.TrackStatusResponse{ | ||||||
| 				Ok: true, | 				Ok: true, | ||||||
| @ -1094,13 +1099,20 @@ func TestCheckAccountStatus(t *testing.T) { | |||||||
| 				}{ | 				}{ | ||||||
| 					Transaction: models.Transaction{ | 					Transaction: models.Transaction{ | ||||||
| 						CreatedAt:     time.Now(), | 						CreatedAt:     time.Now(), | ||||||
| 						Status:        "IN_NETWORK", | 						Status:        "SUCCESS", | ||||||
| 						TransferValue: json.Number("0.5"), | 						TransferValue: json.Number("0.5"), | ||||||
| 						TxHash:        "0x123abc456def", | 						TxHash:        "0x123abc456def", | ||||||
| 						TxType:        "transfer", | 						TxType:        "transfer", | ||||||
| 					}, | 					}, | ||||||
| 				}, | 				}, | ||||||
| 			}, | 			}, | ||||||
|  | 			serverResponse: &api.OKResponse{ | ||||||
|  | 				Ok:          true, | ||||||
|  | 				Description: "Account creation succeeded", | ||||||
|  | 				Result: map[string]any{ | ||||||
|  | 					"active": false, | ||||||
|  | 				}, | ||||||
|  | 			}, | ||||||
| 			expectedResult: resource.Result{ | 			expectedResult: resource.Result{ | ||||||
| 				FlagSet:   []uint32{flag_account_pending}, | 				FlagSet:   []uint32{flag_account_pending}, | ||||||
| 				FlagReset: []uint32{flag_api_error, flag_account_success}, | 				FlagReset: []uint32{flag_api_error, flag_account_success}, | ||||||
| @ -1120,9 +1132,10 @@ func TestCheckAccountStatus(t *testing.T) { | |||||||
| 
 | 
 | ||||||
| 			status := tt.response.Result.Transaction.Status | 			status := tt.response.Result.Transaction.Status | ||||||
| 			// Define expected interactions with the mock
 | 			// Define expected interactions with the mock
 | ||||||
| 			mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_TRACKING_ID).Return(tt.input, nil) | 			mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_PUBLIC_KEY).Return(tt.input, nil) | ||||||
| 
 | 
 | ||||||
| 			mockCreateAccountService.On("CheckAccountStatus", string(tt.input)).Return(tt.response, nil) | 			mockCreateAccountService.On("CheckAccountStatus", string(tt.input)).Return(tt.response, nil) | ||||||
|  | 			mockCreateAccountService.On("TrackAccountStatus", string(tt.input)).Return(tt.serverResponse, nil) | ||||||
| 			mockDataStore.On("WriteEntry", ctx, sessionId, utils.DATA_ACCOUNT_STATUS, []byte(status)).Return(nil).Maybe() | 			mockDataStore.On("WriteEntry", ctx, sessionId, utils.DATA_ACCOUNT_STATUS, []byte(status)).Return(nil).Maybe() | ||||||
| 
 | 
 | ||||||
| 			// Call the method under test
 | 			// Call the method under test
 | ||||||
|  | |||||||
| @ -1,7 +1,10 @@ | |||||||
| package mocks | package mocks | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
|  | 	"context" | ||||||
|  | 
 | ||||||
| 	"git.grassecon.net/urdt/ussd/internal/models" | 	"git.grassecon.net/urdt/ussd/internal/models" | ||||||
|  | 	"github.com/grassrootseconomics/eth-custodial/pkg/api" | ||||||
| 	"github.com/stretchr/testify/mock" | 	"github.com/stretchr/testify/mock" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| @ -10,21 +13,27 @@ type MockAccountService struct { | |||||||
| 	mock.Mock | 	mock.Mock | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (m *MockAccountService) CreateAccount() (*models.AccountResponse, error) { | func (m *MockAccountService) CreateAccount(ctx context.Context) (*api.OKResponse, error) { | ||||||
| 	args := m.Called() | 	args := m.Called() | ||||||
| 	return args.Get(0).(*models.AccountResponse), args.Error(1) | 	return args.Get(0).(*api.OKResponse), args.Error(1) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (m *MockAccountService) CheckBalance(publicKey string) (*models.BalanceResponse, error) { | func (m *MockAccountService) CheckBalance(ctx context.Context, publicKey string) (*models.BalanceResponse, error) { | ||||||
| 	args := m.Called(publicKey) | 	args := m.Called(publicKey) | ||||||
| 	return args.Get(0).(*models.BalanceResponse), args.Error(1) | 	return args.Get(0).(*models.BalanceResponse), args.Error(1) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (m *MockAccountService) CheckAccountStatus(trackingId string) (*models.TrackStatusResponse, error) { | func (m *MockAccountService) CheckAccountStatus(ctx context.Context, trackingId string) (*models.TrackStatusResponse, error) { | ||||||
| 	args := m.Called(trackingId) | 	args := m.Called(trackingId) | ||||||
| 	return args.Get(0).(*models.TrackStatusResponse), args.Error(1) | 	return args.Get(0).(*models.TrackStatusResponse), args.Error(1) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func (m *MockAccountService) TrackAccountStatus(ctx context.Context,publicKey string) (*api.OKResponse, error) { | ||||||
|  | 	args := m.Called(publicKey) | ||||||
|  | 	return args.Get(0).(*api.OKResponse), args.Error(1) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| func (m *MockAccountService) FetchVouchers(publicKey string) (*models.VoucherHoldingResponse, error) { | func (m *MockAccountService) FetchVouchers(publicKey string) (*models.VoucherHoldingResponse, error) { | ||||||
| 	args := m.Called(publicKey) | 	args := m.Called(publicKey) | ||||||
| 	return args.Get(0).(*models.VoucherHoldingResponse), args.Error(1) | 	return args.Get(0).(*models.VoucherHoldingResponse), args.Error(1) | ||||||
|  | |||||||
| @ -1,15 +1,10 @@ | |||||||
| package models | package models | ||||||
| 
 | 
 | ||||||
| import ( |  | ||||||
| 	"encoding/json" |  | ||||||
| 
 |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| type AccountResponse struct { | type AccountResponse struct { | ||||||
| 	Ok     bool `json:"ok"` | 	Ok          bool   `json:"ok"` | ||||||
| 	Result struct { | 	Description string `json:"description"` // Include the description field
 | ||||||
| 		CustodialId json.Number `json:"custodialId"` | 	Result      struct { | ||||||
| 		PublicKey   string      `json:"publicKey"` | 		PublicKey  string `json:"publicKey"` | ||||||
| 		TrackingId  string      `json:"trackingId"` | 		TrackingId string `json:"trackingId"` | ||||||
| 	} `json:"result"` | 	} `json:"result"` | ||||||
| } | } | ||||||
|  | |||||||
| @ -4,7 +4,6 @@ import ( | |||||||
| 	"encoding/json" | 	"encoding/json" | ||||||
| 	"time" | 	"time" | ||||||
| ) | ) | ||||||
| 
 |  | ||||||
| type Transaction struct { | type Transaction struct { | ||||||
| 	CreatedAt     time.Time   `json:"createdAt"` | 	CreatedAt     time.Time   `json:"createdAt"` | ||||||
| 	Status        string      `json:"status"` | 	Status        string      `json:"status"` | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user