double-sided quotation + fixed tests
This commit is contained in:
@@ -18,7 +18,7 @@ require (
|
|||||||
require (
|
require (
|
||||||
github.com/beorn7/perks v1.0.1 // indirect
|
github.com/beorn7/perks v1.0.1 // indirect
|
||||||
github.com/bmatcuk/doublestar/v4 v4.9.1 // indirect
|
github.com/bmatcuk/doublestar/v4 v4.9.1 // indirect
|
||||||
github.com/casbin/casbin/v2 v2.134.0 // indirect
|
github.com/casbin/casbin/v2 v2.135.0 // indirect
|
||||||
github.com/casbin/govaluate v1.10.0 // indirect
|
github.com/casbin/govaluate v1.10.0 // indirect
|
||||||
github.com/casbin/mongodb-adapter/v3 v3.7.0 // indirect
|
github.com/casbin/mongodb-adapter/v3 v3.7.0 // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
|
|||||||
github.com/bmatcuk/doublestar/v4 v4.6.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
|
github.com/bmatcuk/doublestar/v4 v4.6.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
|
||||||
github.com/bmatcuk/doublestar/v4 v4.9.1 h1:X8jg9rRZmJd4yRy7ZeNDRnM+T3ZfHv15JiBJ/avrEXE=
|
github.com/bmatcuk/doublestar/v4 v4.9.1 h1:X8jg9rRZmJd4yRy7ZeNDRnM+T3ZfHv15JiBJ/avrEXE=
|
||||||
github.com/bmatcuk/doublestar/v4 v4.9.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
|
github.com/bmatcuk/doublestar/v4 v4.9.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
|
||||||
github.com/casbin/casbin/v2 v2.134.0 h1:wyO3hZb487GzlGVAI2hUoHQT0ehFD+9B5P+HVG9BVTM=
|
github.com/casbin/casbin/v2 v2.135.0 h1:6BLkMQiGotYyS5yYeWgW19vxqugUlvHFkFiLnLR/bxk=
|
||||||
github.com/casbin/casbin/v2 v2.134.0/go.mod h1:FmcfntdXLTcYXv/hxgNntcRPqAbwOG9xsism0yXT+18=
|
github.com/casbin/casbin/v2 v2.135.0/go.mod h1:FmcfntdXLTcYXv/hxgNntcRPqAbwOG9xsism0yXT+18=
|
||||||
github.com/casbin/govaluate v1.3.0/go.mod h1:G/UnbIjZk/0uMNaLwZZmFQrR72tYRZWQkO70si/iR7A=
|
github.com/casbin/govaluate v1.3.0/go.mod h1:G/UnbIjZk/0uMNaLwZZmFQrR72tYRZWQkO70si/iR7A=
|
||||||
github.com/casbin/govaluate v1.10.0 h1:ffGw51/hYH3w3rZcxO/KcaUIDOLP84w7nsidMVgaDG0=
|
github.com/casbin/govaluate v1.10.0 h1:ffGw51/hYH3w3rZcxO/KcaUIDOLP84w7nsidMVgaDG0=
|
||||||
github.com/casbin/govaluate v1.10.0/go.mod h1:G/UnbIjZk/0uMNaLwZZmFQrR72tYRZWQkO70si/iR7A=
|
github.com/casbin/govaluate v1.10.0/go.mod h1:G/UnbIjZk/0uMNaLwZZmFQrR72tYRZWQkO70si/iR7A=
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ require (
|
|||||||
require (
|
require (
|
||||||
github.com/beorn7/perks v1.0.1 // indirect
|
github.com/beorn7/perks v1.0.1 // indirect
|
||||||
github.com/bmatcuk/doublestar/v4 v4.9.1 // indirect
|
github.com/bmatcuk/doublestar/v4 v4.9.1 // indirect
|
||||||
github.com/casbin/casbin/v2 v2.134.0 // indirect
|
github.com/casbin/casbin/v2 v2.135.0 // indirect
|
||||||
github.com/casbin/govaluate v1.10.0 // indirect
|
github.com/casbin/govaluate v1.10.0 // indirect
|
||||||
github.com/casbin/mongodb-adapter/v3 v3.7.0 // indirect
|
github.com/casbin/mongodb-adapter/v3 v3.7.0 // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
|
|||||||
github.com/bmatcuk/doublestar/v4 v4.6.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
|
github.com/bmatcuk/doublestar/v4 v4.6.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
|
||||||
github.com/bmatcuk/doublestar/v4 v4.9.1 h1:X8jg9rRZmJd4yRy7ZeNDRnM+T3ZfHv15JiBJ/avrEXE=
|
github.com/bmatcuk/doublestar/v4 v4.9.1 h1:X8jg9rRZmJd4yRy7ZeNDRnM+T3ZfHv15JiBJ/avrEXE=
|
||||||
github.com/bmatcuk/doublestar/v4 v4.9.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
|
github.com/bmatcuk/doublestar/v4 v4.9.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
|
||||||
github.com/casbin/casbin/v2 v2.134.0 h1:wyO3hZb487GzlGVAI2hUoHQT0ehFD+9B5P+HVG9BVTM=
|
github.com/casbin/casbin/v2 v2.135.0 h1:6BLkMQiGotYyS5yYeWgW19vxqugUlvHFkFiLnLR/bxk=
|
||||||
github.com/casbin/casbin/v2 v2.134.0/go.mod h1:FmcfntdXLTcYXv/hxgNntcRPqAbwOG9xsism0yXT+18=
|
github.com/casbin/casbin/v2 v2.135.0/go.mod h1:FmcfntdXLTcYXv/hxgNntcRPqAbwOG9xsism0yXT+18=
|
||||||
github.com/casbin/govaluate v1.3.0/go.mod h1:G/UnbIjZk/0uMNaLwZZmFQrR72tYRZWQkO70si/iR7A=
|
github.com/casbin/govaluate v1.3.0/go.mod h1:G/UnbIjZk/0uMNaLwZZmFQrR72tYRZWQkO70si/iR7A=
|
||||||
github.com/casbin/govaluate v1.10.0 h1:ffGw51/hYH3w3rZcxO/KcaUIDOLP84w7nsidMVgaDG0=
|
github.com/casbin/govaluate v1.10.0 h1:ffGw51/hYH3w3rZcxO/KcaUIDOLP84w7nsidMVgaDG0=
|
||||||
github.com/casbin/govaluate v1.10.0/go.mod h1:G/UnbIjZk/0uMNaLwZZmFQrR72tYRZWQkO70si/iR7A=
|
github.com/casbin/govaluate v1.10.0/go.mod h1:G/UnbIjZk/0uMNaLwZZmFQrR72tYRZWQkO70si/iR7A=
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ require (
|
|||||||
require (
|
require (
|
||||||
github.com/beorn7/perks v1.0.1 // indirect
|
github.com/beorn7/perks v1.0.1 // indirect
|
||||||
github.com/bmatcuk/doublestar/v4 v4.9.1 // indirect
|
github.com/bmatcuk/doublestar/v4 v4.9.1 // indirect
|
||||||
github.com/casbin/casbin/v2 v2.134.0 // indirect
|
github.com/casbin/casbin/v2 v2.135.0 // indirect
|
||||||
github.com/casbin/govaluate v1.10.0 // indirect
|
github.com/casbin/govaluate v1.10.0 // indirect
|
||||||
github.com/casbin/mongodb-adapter/v3 v3.7.0 // indirect
|
github.com/casbin/mongodb-adapter/v3 v3.7.0 // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
|
|||||||
github.com/bmatcuk/doublestar/v4 v4.6.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
|
github.com/bmatcuk/doublestar/v4 v4.6.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
|
||||||
github.com/bmatcuk/doublestar/v4 v4.9.1 h1:X8jg9rRZmJd4yRy7ZeNDRnM+T3ZfHv15JiBJ/avrEXE=
|
github.com/bmatcuk/doublestar/v4 v4.9.1 h1:X8jg9rRZmJd4yRy7ZeNDRnM+T3ZfHv15JiBJ/avrEXE=
|
||||||
github.com/bmatcuk/doublestar/v4 v4.9.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
|
github.com/bmatcuk/doublestar/v4 v4.9.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
|
||||||
github.com/casbin/casbin/v2 v2.134.0 h1:wyO3hZb487GzlGVAI2hUoHQT0ehFD+9B5P+HVG9BVTM=
|
github.com/casbin/casbin/v2 v2.135.0 h1:6BLkMQiGotYyS5yYeWgW19vxqugUlvHFkFiLnLR/bxk=
|
||||||
github.com/casbin/casbin/v2 v2.134.0/go.mod h1:FmcfntdXLTcYXv/hxgNntcRPqAbwOG9xsism0yXT+18=
|
github.com/casbin/casbin/v2 v2.135.0/go.mod h1:FmcfntdXLTcYXv/hxgNntcRPqAbwOG9xsism0yXT+18=
|
||||||
github.com/casbin/govaluate v1.3.0/go.mod h1:G/UnbIjZk/0uMNaLwZZmFQrR72tYRZWQkO70si/iR7A=
|
github.com/casbin/govaluate v1.3.0/go.mod h1:G/UnbIjZk/0uMNaLwZZmFQrR72tYRZWQkO70si/iR7A=
|
||||||
github.com/casbin/govaluate v1.10.0 h1:ffGw51/hYH3w3rZcxO/KcaUIDOLP84w7nsidMVgaDG0=
|
github.com/casbin/govaluate v1.10.0 h1:ffGw51/hYH3w3rZcxO/KcaUIDOLP84w7nsidMVgaDG0=
|
||||||
github.com/casbin/govaluate v1.10.0/go.mod h1:G/UnbIjZk/0uMNaLwZZmFQrR72tYRZWQkO70si/iR7A=
|
github.com/casbin/govaluate v1.10.0/go.mod h1:G/UnbIjZk/0uMNaLwZZmFQrR72tYRZWQkO70si/iR7A=
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ require (
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/bmatcuk/doublestar/v4 v4.9.1 // indirect
|
github.com/bmatcuk/doublestar/v4 v4.9.1 // indirect
|
||||||
github.com/casbin/casbin/v2 v2.134.0 // indirect
|
github.com/casbin/casbin/v2 v2.135.0 // indirect
|
||||||
github.com/casbin/govaluate v1.10.0 // indirect
|
github.com/casbin/govaluate v1.10.0 // indirect
|
||||||
github.com/casbin/mongodb-adapter/v3 v3.7.0 // indirect
|
github.com/casbin/mongodb-adapter/v3 v3.7.0 // indirect
|
||||||
github.com/golang/snappy v1.0.0 // indirect
|
github.com/golang/snappy v1.0.0 // indirect
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA
|
|||||||
github.com/bmatcuk/doublestar/v4 v4.6.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
|
github.com/bmatcuk/doublestar/v4 v4.6.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
|
||||||
github.com/bmatcuk/doublestar/v4 v4.9.1 h1:X8jg9rRZmJd4yRy7ZeNDRnM+T3ZfHv15JiBJ/avrEXE=
|
github.com/bmatcuk/doublestar/v4 v4.9.1 h1:X8jg9rRZmJd4yRy7ZeNDRnM+T3ZfHv15JiBJ/avrEXE=
|
||||||
github.com/bmatcuk/doublestar/v4 v4.9.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
|
github.com/bmatcuk/doublestar/v4 v4.9.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
|
||||||
github.com/casbin/casbin/v2 v2.134.0 h1:wyO3hZb487GzlGVAI2hUoHQT0ehFD+9B5P+HVG9BVTM=
|
github.com/casbin/casbin/v2 v2.135.0 h1:6BLkMQiGotYyS5yYeWgW19vxqugUlvHFkFiLnLR/bxk=
|
||||||
github.com/casbin/casbin/v2 v2.134.0/go.mod h1:FmcfntdXLTcYXv/hxgNntcRPqAbwOG9xsism0yXT+18=
|
github.com/casbin/casbin/v2 v2.135.0/go.mod h1:FmcfntdXLTcYXv/hxgNntcRPqAbwOG9xsism0yXT+18=
|
||||||
github.com/casbin/govaluate v1.3.0/go.mod h1:G/UnbIjZk/0uMNaLwZZmFQrR72tYRZWQkO70si/iR7A=
|
github.com/casbin/govaluate v1.3.0/go.mod h1:G/UnbIjZk/0uMNaLwZZmFQrR72tYRZWQkO70si/iR7A=
|
||||||
github.com/casbin/govaluate v1.10.0 h1:ffGw51/hYH3w3rZcxO/KcaUIDOLP84w7nsidMVgaDG0=
|
github.com/casbin/govaluate v1.10.0 h1:ffGw51/hYH3w3rZcxO/KcaUIDOLP84w7nsidMVgaDG0=
|
||||||
github.com/casbin/govaluate v1.10.0/go.mod h1:G/UnbIjZk/0uMNaLwZZmFQrR72tYRZWQkO70si/iR7A=
|
github.com/casbin/govaluate v1.10.0/go.mod h1:G/UnbIjZk/0uMNaLwZZmFQrR72tYRZWQkO70si/iR7A=
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ require (
|
|||||||
github.com/beorn7/perks v1.0.1 // indirect
|
github.com/beorn7/perks v1.0.1 // indirect
|
||||||
github.com/bits-and-blooms/bitset v1.24.4 // indirect
|
github.com/bits-and-blooms/bitset v1.24.4 // indirect
|
||||||
github.com/bmatcuk/doublestar/v4 v4.9.1 // indirect
|
github.com/bmatcuk/doublestar/v4 v4.9.1 // indirect
|
||||||
github.com/casbin/casbin/v2 v2.134.0 // indirect
|
github.com/casbin/casbin/v2 v2.135.0 // indirect
|
||||||
github.com/casbin/govaluate v1.10.0 // indirect
|
github.com/casbin/govaluate v1.10.0 // indirect
|
||||||
github.com/casbin/mongodb-adapter/v3 v3.7.0 // indirect
|
github.com/casbin/mongodb-adapter/v3 v3.7.0 // indirect
|
||||||
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
||||||
|
|||||||
@@ -17,8 +17,8 @@ github.com/bits-and-blooms/bitset v1.24.4/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6
|
|||||||
github.com/bmatcuk/doublestar/v4 v4.6.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
|
github.com/bmatcuk/doublestar/v4 v4.6.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
|
||||||
github.com/bmatcuk/doublestar/v4 v4.9.1 h1:X8jg9rRZmJd4yRy7ZeNDRnM+T3ZfHv15JiBJ/avrEXE=
|
github.com/bmatcuk/doublestar/v4 v4.9.1 h1:X8jg9rRZmJd4yRy7ZeNDRnM+T3ZfHv15JiBJ/avrEXE=
|
||||||
github.com/bmatcuk/doublestar/v4 v4.9.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
|
github.com/bmatcuk/doublestar/v4 v4.9.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
|
||||||
github.com/casbin/casbin/v2 v2.134.0 h1:wyO3hZb487GzlGVAI2hUoHQT0ehFD+9B5P+HVG9BVTM=
|
github.com/casbin/casbin/v2 v2.135.0 h1:6BLkMQiGotYyS5yYeWgW19vxqugUlvHFkFiLnLR/bxk=
|
||||||
github.com/casbin/casbin/v2 v2.134.0/go.mod h1:FmcfntdXLTcYXv/hxgNntcRPqAbwOG9xsism0yXT+18=
|
github.com/casbin/casbin/v2 v2.135.0/go.mod h1:FmcfntdXLTcYXv/hxgNntcRPqAbwOG9xsism0yXT+18=
|
||||||
github.com/casbin/govaluate v1.3.0/go.mod h1:G/UnbIjZk/0uMNaLwZZmFQrR72tYRZWQkO70si/iR7A=
|
github.com/casbin/govaluate v1.3.0/go.mod h1:G/UnbIjZk/0uMNaLwZZmFQrR72tYRZWQkO70si/iR7A=
|
||||||
github.com/casbin/govaluate v1.10.0 h1:ffGw51/hYH3w3rZcxO/KcaUIDOLP84w7nsidMVgaDG0=
|
github.com/casbin/govaluate v1.10.0 h1:ffGw51/hYH3w3rZcxO/KcaUIDOLP84w7nsidMVgaDG0=
|
||||||
github.com/casbin/govaluate v1.10.0/go.mod h1:G/UnbIjZk/0uMNaLwZZmFQrR72tYRZWQkO70si/iR7A=
|
github.com/casbin/govaluate v1.10.0/go.mod h1:G/UnbIjZk/0uMNaLwZZmFQrR72tYRZWQkO70si/iR7A=
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ require (
|
|||||||
require (
|
require (
|
||||||
github.com/beorn7/perks v1.0.1 // indirect
|
github.com/beorn7/perks v1.0.1 // indirect
|
||||||
github.com/bmatcuk/doublestar/v4 v4.9.1 // indirect
|
github.com/bmatcuk/doublestar/v4 v4.9.1 // indirect
|
||||||
github.com/casbin/casbin/v2 v2.134.0 // indirect
|
github.com/casbin/casbin/v2 v2.135.0 // indirect
|
||||||
github.com/casbin/govaluate v1.10.0 // indirect
|
github.com/casbin/govaluate v1.10.0 // indirect
|
||||||
github.com/casbin/mongodb-adapter/v3 v3.7.0 // indirect
|
github.com/casbin/mongodb-adapter/v3 v3.7.0 // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
|
|||||||
github.com/bmatcuk/doublestar/v4 v4.6.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
|
github.com/bmatcuk/doublestar/v4 v4.6.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
|
||||||
github.com/bmatcuk/doublestar/v4 v4.9.1 h1:X8jg9rRZmJd4yRy7ZeNDRnM+T3ZfHv15JiBJ/avrEXE=
|
github.com/bmatcuk/doublestar/v4 v4.9.1 h1:X8jg9rRZmJd4yRy7ZeNDRnM+T3ZfHv15JiBJ/avrEXE=
|
||||||
github.com/bmatcuk/doublestar/v4 v4.9.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
|
github.com/bmatcuk/doublestar/v4 v4.9.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
|
||||||
github.com/casbin/casbin/v2 v2.134.0 h1:wyO3hZb487GzlGVAI2hUoHQT0ehFD+9B5P+HVG9BVTM=
|
github.com/casbin/casbin/v2 v2.135.0 h1:6BLkMQiGotYyS5yYeWgW19vxqugUlvHFkFiLnLR/bxk=
|
||||||
github.com/casbin/casbin/v2 v2.134.0/go.mod h1:FmcfntdXLTcYXv/hxgNntcRPqAbwOG9xsism0yXT+18=
|
github.com/casbin/casbin/v2 v2.135.0/go.mod h1:FmcfntdXLTcYXv/hxgNntcRPqAbwOG9xsism0yXT+18=
|
||||||
github.com/casbin/govaluate v1.3.0/go.mod h1:G/UnbIjZk/0uMNaLwZZmFQrR72tYRZWQkO70si/iR7A=
|
github.com/casbin/govaluate v1.3.0/go.mod h1:G/UnbIjZk/0uMNaLwZZmFQrR72tYRZWQkO70si/iR7A=
|
||||||
github.com/casbin/govaluate v1.10.0 h1:ffGw51/hYH3w3rZcxO/KcaUIDOLP84w7nsidMVgaDG0=
|
github.com/casbin/govaluate v1.10.0 h1:ffGw51/hYH3w3rZcxO/KcaUIDOLP84w7nsidMVgaDG0=
|
||||||
github.com/casbin/govaluate v1.10.0/go.mod h1:G/UnbIjZk/0uMNaLwZZmFQrR72tYRZWQkO70si/iR7A=
|
github.com/casbin/govaluate v1.10.0/go.mod h1:G/UnbIjZk/0uMNaLwZZmFQrR72tYRZWQkO70si/iR7A=
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ require (
|
|||||||
require (
|
require (
|
||||||
github.com/beorn7/perks v1.0.1 // indirect
|
github.com/beorn7/perks v1.0.1 // indirect
|
||||||
github.com/bmatcuk/doublestar/v4 v4.9.1 // indirect
|
github.com/bmatcuk/doublestar/v4 v4.9.1 // indirect
|
||||||
github.com/casbin/casbin/v2 v2.134.0 // indirect
|
github.com/casbin/casbin/v2 v2.135.0 // indirect
|
||||||
github.com/casbin/govaluate v1.10.0 // indirect
|
github.com/casbin/govaluate v1.10.0 // indirect
|
||||||
github.com/casbin/mongodb-adapter/v3 v3.7.0 // indirect
|
github.com/casbin/mongodb-adapter/v3 v3.7.0 // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
|
|||||||
github.com/bmatcuk/doublestar/v4 v4.6.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
|
github.com/bmatcuk/doublestar/v4 v4.6.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
|
||||||
github.com/bmatcuk/doublestar/v4 v4.9.1 h1:X8jg9rRZmJd4yRy7ZeNDRnM+T3ZfHv15JiBJ/avrEXE=
|
github.com/bmatcuk/doublestar/v4 v4.9.1 h1:X8jg9rRZmJd4yRy7ZeNDRnM+T3ZfHv15JiBJ/avrEXE=
|
||||||
github.com/bmatcuk/doublestar/v4 v4.9.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
|
github.com/bmatcuk/doublestar/v4 v4.9.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
|
||||||
github.com/casbin/casbin/v2 v2.134.0 h1:wyO3hZb487GzlGVAI2hUoHQT0ehFD+9B5P+HVG9BVTM=
|
github.com/casbin/casbin/v2 v2.135.0 h1:6BLkMQiGotYyS5yYeWgW19vxqugUlvHFkFiLnLR/bxk=
|
||||||
github.com/casbin/casbin/v2 v2.134.0/go.mod h1:FmcfntdXLTcYXv/hxgNntcRPqAbwOG9xsism0yXT+18=
|
github.com/casbin/casbin/v2 v2.135.0/go.mod h1:FmcfntdXLTcYXv/hxgNntcRPqAbwOG9xsism0yXT+18=
|
||||||
github.com/casbin/govaluate v1.3.0/go.mod h1:G/UnbIjZk/0uMNaLwZZmFQrR72tYRZWQkO70si/iR7A=
|
github.com/casbin/govaluate v1.3.0/go.mod h1:G/UnbIjZk/0uMNaLwZZmFQrR72tYRZWQkO70si/iR7A=
|
||||||
github.com/casbin/govaluate v1.10.0 h1:ffGw51/hYH3w3rZcxO/KcaUIDOLP84w7nsidMVgaDG0=
|
github.com/casbin/govaluate v1.10.0 h1:ffGw51/hYH3w3rZcxO/KcaUIDOLP84w7nsidMVgaDG0=
|
||||||
github.com/casbin/govaluate v1.10.0/go.mod h1:G/UnbIjZk/0uMNaLwZZmFQrR72tYRZWQkO70si/iR7A=
|
github.com/casbin/govaluate v1.10.0/go.mod h1:G/UnbIjZk/0uMNaLwZZmFQrR72tYRZWQkO70si/iR7A=
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ require (
|
|||||||
require (
|
require (
|
||||||
github.com/beorn7/perks v1.0.1 // indirect
|
github.com/beorn7/perks v1.0.1 // indirect
|
||||||
github.com/bmatcuk/doublestar/v4 v4.9.1 // indirect
|
github.com/bmatcuk/doublestar/v4 v4.9.1 // indirect
|
||||||
github.com/casbin/casbin/v2 v2.134.0 // indirect
|
github.com/casbin/casbin/v2 v2.135.0 // indirect
|
||||||
github.com/casbin/govaluate v1.10.0 // indirect
|
github.com/casbin/govaluate v1.10.0 // indirect
|
||||||
github.com/casbin/mongodb-adapter/v3 v3.7.0 // indirect
|
github.com/casbin/mongodb-adapter/v3 v3.7.0 // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
|
|||||||
github.com/bmatcuk/doublestar/v4 v4.6.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
|
github.com/bmatcuk/doublestar/v4 v4.6.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
|
||||||
github.com/bmatcuk/doublestar/v4 v4.9.1 h1:X8jg9rRZmJd4yRy7ZeNDRnM+T3ZfHv15JiBJ/avrEXE=
|
github.com/bmatcuk/doublestar/v4 v4.9.1 h1:X8jg9rRZmJd4yRy7ZeNDRnM+T3ZfHv15JiBJ/avrEXE=
|
||||||
github.com/bmatcuk/doublestar/v4 v4.9.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
|
github.com/bmatcuk/doublestar/v4 v4.9.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
|
||||||
github.com/casbin/casbin/v2 v2.134.0 h1:wyO3hZb487GzlGVAI2hUoHQT0ehFD+9B5P+HVG9BVTM=
|
github.com/casbin/casbin/v2 v2.135.0 h1:6BLkMQiGotYyS5yYeWgW19vxqugUlvHFkFiLnLR/bxk=
|
||||||
github.com/casbin/casbin/v2 v2.134.0/go.mod h1:FmcfntdXLTcYXv/hxgNntcRPqAbwOG9xsism0yXT+18=
|
github.com/casbin/casbin/v2 v2.135.0/go.mod h1:FmcfntdXLTcYXv/hxgNntcRPqAbwOG9xsism0yXT+18=
|
||||||
github.com/casbin/govaluate v1.3.0/go.mod h1:G/UnbIjZk/0uMNaLwZZmFQrR72tYRZWQkO70si/iR7A=
|
github.com/casbin/govaluate v1.3.0/go.mod h1:G/UnbIjZk/0uMNaLwZZmFQrR72tYRZWQkO70si/iR7A=
|
||||||
github.com/casbin/govaluate v1.10.0 h1:ffGw51/hYH3w3rZcxO/KcaUIDOLP84w7nsidMVgaDG0=
|
github.com/casbin/govaluate v1.10.0 h1:ffGw51/hYH3w3rZcxO/KcaUIDOLP84w7nsidMVgaDG0=
|
||||||
github.com/casbin/govaluate v1.10.0/go.mod h1:G/UnbIjZk/0uMNaLwZZmFQrR72tYRZWQkO70si/iR7A=
|
github.com/casbin/govaluate v1.10.0/go.mod h1:G/UnbIjZk/0uMNaLwZZmFQrR72tYRZWQkO70si/iR7A=
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ require (
|
|||||||
require (
|
require (
|
||||||
github.com/beorn7/perks v1.0.1 // indirect
|
github.com/beorn7/perks v1.0.1 // indirect
|
||||||
github.com/bmatcuk/doublestar/v4 v4.9.1 // indirect
|
github.com/bmatcuk/doublestar/v4 v4.9.1 // indirect
|
||||||
github.com/casbin/casbin/v2 v2.134.0 // indirect
|
github.com/casbin/casbin/v2 v2.135.0 // indirect
|
||||||
github.com/casbin/govaluate v1.10.0 // indirect
|
github.com/casbin/govaluate v1.10.0 // indirect
|
||||||
github.com/casbin/mongodb-adapter/v3 v3.7.0 // indirect
|
github.com/casbin/mongodb-adapter/v3 v3.7.0 // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
|
|||||||
github.com/bmatcuk/doublestar/v4 v4.6.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
|
github.com/bmatcuk/doublestar/v4 v4.6.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
|
||||||
github.com/bmatcuk/doublestar/v4 v4.9.1 h1:X8jg9rRZmJd4yRy7ZeNDRnM+T3ZfHv15JiBJ/avrEXE=
|
github.com/bmatcuk/doublestar/v4 v4.9.1 h1:X8jg9rRZmJd4yRy7ZeNDRnM+T3ZfHv15JiBJ/avrEXE=
|
||||||
github.com/bmatcuk/doublestar/v4 v4.9.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
|
github.com/bmatcuk/doublestar/v4 v4.9.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
|
||||||
github.com/casbin/casbin/v2 v2.134.0 h1:wyO3hZb487GzlGVAI2hUoHQT0ehFD+9B5P+HVG9BVTM=
|
github.com/casbin/casbin/v2 v2.135.0 h1:6BLkMQiGotYyS5yYeWgW19vxqugUlvHFkFiLnLR/bxk=
|
||||||
github.com/casbin/casbin/v2 v2.134.0/go.mod h1:FmcfntdXLTcYXv/hxgNntcRPqAbwOG9xsism0yXT+18=
|
github.com/casbin/casbin/v2 v2.135.0/go.mod h1:FmcfntdXLTcYXv/hxgNntcRPqAbwOG9xsism0yXT+18=
|
||||||
github.com/casbin/govaluate v1.3.0/go.mod h1:G/UnbIjZk/0uMNaLwZZmFQrR72tYRZWQkO70si/iR7A=
|
github.com/casbin/govaluate v1.3.0/go.mod h1:G/UnbIjZk/0uMNaLwZZmFQrR72tYRZWQkO70si/iR7A=
|
||||||
github.com/casbin/govaluate v1.10.0 h1:ffGw51/hYH3w3rZcxO/KcaUIDOLP84w7nsidMVgaDG0=
|
github.com/casbin/govaluate v1.10.0 h1:ffGw51/hYH3w3rZcxO/KcaUIDOLP84w7nsidMVgaDG0=
|
||||||
github.com/casbin/govaluate v1.10.0/go.mod h1:G/UnbIjZk/0uMNaLwZZmFQrR72tYRZWQkO70si/iR7A=
|
github.com/casbin/govaluate v1.10.0/go.mod h1:G/UnbIjZk/0uMNaLwZZmFQrR72tYRZWQkO70si/iR7A=
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ import (
|
|||||||
"github.com/tech/sendico/payments/orchestrator/storage/model"
|
"github.com/tech/sendico/payments/orchestrator/storage/model"
|
||||||
"github.com/tech/sendico/pkg/merrors"
|
"github.com/tech/sendico/pkg/merrors"
|
||||||
feesv1 "github.com/tech/sendico/pkg/proto/billing/fees/v1"
|
feesv1 "github.com/tech/sendico/pkg/proto/billing/fees/v1"
|
||||||
|
fxv1 "github.com/tech/sendico/pkg/proto/common/fx/v1"
|
||||||
|
moneyv1 "github.com/tech/sendico/pkg/proto/common/money/v1"
|
||||||
chainv1 "github.com/tech/sendico/pkg/proto/gateway/chain/v1"
|
chainv1 "github.com/tech/sendico/pkg/proto/gateway/chain/v1"
|
||||||
ledgerv1 "github.com/tech/sendico/pkg/proto/ledger/v1"
|
ledgerv1 "github.com/tech/sendico/pkg/proto/ledger/v1"
|
||||||
oraclev1 "github.com/tech/sendico/pkg/proto/oracle/v1"
|
oraclev1 "github.com/tech/sendico/pkg/proto/oracle/v1"
|
||||||
@@ -22,12 +24,38 @@ import (
|
|||||||
func (s *Service) buildPaymentQuote(ctx context.Context, orgRef string, req *orchestratorv1.QuotePaymentRequest) (*orchestratorv1.PaymentQuote, time.Time, error) {
|
func (s *Service) buildPaymentQuote(ctx context.Context, orgRef string, req *orchestratorv1.QuotePaymentRequest) (*orchestratorv1.PaymentQuote, time.Time, error) {
|
||||||
intent := req.GetIntent()
|
intent := req.GetIntent()
|
||||||
amount := intent.GetAmount()
|
amount := intent.GetAmount()
|
||||||
baseAmount := cloneMoney(amount)
|
fxSide := fxv1.Side_SIDE_UNSPECIFIED
|
||||||
feeQuote, err := s.quoteFees(ctx, orgRef, req)
|
if intent.GetFx() != nil {
|
||||||
|
fxSide = intent.GetFx().GetSide()
|
||||||
|
}
|
||||||
|
|
||||||
|
var fxQuote *oraclev1.Quote
|
||||||
|
var err error
|
||||||
|
if shouldRequestFX(intent) {
|
||||||
|
fxQuote, err = s.requestFXQuote(ctx, orgRef, req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, time.Time{}, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
payAmount, settlementAmountBeforeFees := resolveTradeAmounts(amount, fxQuote, fxSide)
|
||||||
|
|
||||||
|
feeBaseAmount := payAmount
|
||||||
|
if feeBaseAmount == nil {
|
||||||
|
feeBaseAmount = cloneMoney(amount)
|
||||||
|
}
|
||||||
|
|
||||||
|
feeQuote, err := s.quoteFees(ctx, orgRef, req, feeBaseAmount)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, time.Time{}, err
|
return nil, time.Time{}, err
|
||||||
}
|
}
|
||||||
feeTotal := extractFeeTotal(feeQuote.GetLines(), amount.GetCurrency())
|
feeCurrency := ""
|
||||||
|
if feeBaseAmount != nil {
|
||||||
|
feeCurrency = feeBaseAmount.GetCurrency()
|
||||||
|
} else if amount != nil {
|
||||||
|
feeCurrency = amount.GetCurrency()
|
||||||
|
}
|
||||||
|
feeTotal := extractFeeTotal(feeQuote.GetLines(), feeCurrency)
|
||||||
|
|
||||||
var networkFee *chainv1.EstimateTransferFeeResponse
|
var networkFee *chainv1.EstimateTransferFeeResponse
|
||||||
if shouldEstimateNetworkFee(intent) {
|
if shouldEstimateNetworkFee(intent) {
|
||||||
@@ -37,15 +65,7 @@ func (s *Service) buildPaymentQuote(ctx context.Context, orgRef string, req *orc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var fxQuote *oraclev1.Quote
|
debitAmount, settlementAmount := computeAggregates(payAmount, settlementAmountBeforeFees, feeTotal, networkFee, fxQuote)
|
||||||
if shouldRequestFX(intent) {
|
|
||||||
fxQuote, err = s.requestFXQuote(ctx, orgRef, req)
|
|
||||||
if err != nil {
|
|
||||||
return nil, time.Time{}, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
debitAmount, settlementAmount := computeAggregates(baseAmount, feeTotal, networkFee)
|
|
||||||
|
|
||||||
quote := &orchestratorv1.PaymentQuote{
|
quote := &orchestratorv1.PaymentQuote{
|
||||||
DebitAmount: debitAmount,
|
DebitAmount: debitAmount,
|
||||||
@@ -63,14 +83,18 @@ func (s *Service) buildPaymentQuote(ctx context.Context, orgRef string, req *orc
|
|||||||
return quote, expiresAt, nil
|
return quote, expiresAt, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) quoteFees(ctx context.Context, orgRef string, req *orchestratorv1.QuotePaymentRequest) (*feesv1.PrecomputeFeesResponse, error) {
|
func (s *Service) quoteFees(ctx context.Context, orgRef string, req *orchestratorv1.QuotePaymentRequest, baseAmount *moneyv1.Money) (*feesv1.PrecomputeFeesResponse, error) {
|
||||||
if !s.fees.available() {
|
if !s.fees.available() {
|
||||||
return &feesv1.PrecomputeFeesResponse{}, nil
|
return &feesv1.PrecomputeFeesResponse{}, nil
|
||||||
}
|
}
|
||||||
intent := req.GetIntent()
|
intent := req.GetIntent()
|
||||||
|
amount := cloneMoney(baseAmount)
|
||||||
|
if amount == nil {
|
||||||
|
amount = cloneMoney(intent.GetAmount())
|
||||||
|
}
|
||||||
feeIntent := &feesv1.Intent{
|
feeIntent := &feesv1.Intent{
|
||||||
Trigger: triggerFromKind(intent.GetKind(), intent.GetRequiresFx()),
|
Trigger: triggerFromKind(intent.GetKind(), intent.GetRequiresFx()),
|
||||||
BaseAmount: cloneMoney(intent.GetAmount()),
|
BaseAmount: amount,
|
||||||
BookedAt: timestamppb.New(s.clock.Now()),
|
BookedAt: timestamppb.New(s.clock.Now()),
|
||||||
OriginType: "payments.orchestrator.quote",
|
OriginType: "payments.orchestrator.quote",
|
||||||
OriginRef: strings.TrimSpace(req.GetIdempotencyKey()),
|
OriginRef: strings.TrimSpace(req.GetIdempotencyKey()),
|
||||||
@@ -164,7 +188,19 @@ func (s *Service) requestFXQuote(ctx context.Context, orgRef string, req *orches
|
|||||||
}
|
}
|
||||||
|
|
||||||
if amount := intent.GetAmount(); amount != nil {
|
if amount := intent.GetAmount(); amount != nil {
|
||||||
params.BaseAmount = cloneMoney(amount)
|
pair := fxIntent.GetPair()
|
||||||
|
if pair != nil {
|
||||||
|
switch {
|
||||||
|
case strings.EqualFold(amount.GetCurrency(), pair.GetBase()):
|
||||||
|
params.BaseAmount = cloneMoney(amount)
|
||||||
|
case strings.EqualFold(amount.GetCurrency(), pair.GetQuote()):
|
||||||
|
params.QuoteAmount = cloneMoney(amount)
|
||||||
|
default:
|
||||||
|
params.BaseAmount = cloneMoney(amount)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
params.BaseAmount = cloneMoney(amount)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
quote, err := s.oracle.client.GetQuote(ctx, params)
|
quote, err := s.oracle.client.GetQuote(ctx, params)
|
||||||
@@ -291,11 +327,14 @@ func (s *Service) applyFX(ctx context.Context, payment *model.Payment, quote *or
|
|||||||
if fq == nil {
|
if fq == nil {
|
||||||
return merrors.InvalidArgument("ledger: fx quote missing")
|
return merrors.InvalidArgument("ledger: fx quote missing")
|
||||||
}
|
}
|
||||||
fromMoney := cloneMoney(fq.GetBaseAmount())
|
fxSide := fxv1.Side_SIDE_UNSPECIFIED
|
||||||
|
if intent.FX != nil {
|
||||||
|
fxSide = intent.FX.Side
|
||||||
|
}
|
||||||
|
fromMoney, toMoney := resolveTradeAmounts(intent.Amount, fq, fxSide)
|
||||||
if fromMoney == nil {
|
if fromMoney == nil {
|
||||||
fromMoney = cloneMoney(intent.Amount)
|
fromMoney = cloneMoney(intent.Amount)
|
||||||
}
|
}
|
||||||
toMoney := cloneMoney(fq.GetQuoteAmount())
|
|
||||||
if toMoney == nil {
|
if toMoney == nil {
|
||||||
toMoney = cloneMoney(quote.GetExpectedSettlementAmount())
|
toMoney = cloneMoney(quote.GetExpectedSettlementAmount())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import (
|
|||||||
|
|
||||||
feesv1 "github.com/tech/sendico/pkg/proto/billing/fees/v1"
|
feesv1 "github.com/tech/sendico/pkg/proto/billing/fees/v1"
|
||||||
accountingv1 "github.com/tech/sendico/pkg/proto/common/accounting/v1"
|
accountingv1 "github.com/tech/sendico/pkg/proto/common/accounting/v1"
|
||||||
|
fxv1 "github.com/tech/sendico/pkg/proto/common/fx/v1"
|
||||||
moneyv1 "github.com/tech/sendico/pkg/proto/common/money/v1"
|
moneyv1 "github.com/tech/sendico/pkg/proto/common/money/v1"
|
||||||
chainv1 "github.com/tech/sendico/pkg/proto/gateway/chain/v1"
|
chainv1 "github.com/tech/sendico/pkg/proto/gateway/chain/v1"
|
||||||
)
|
)
|
||||||
@@ -109,30 +110,91 @@ func extractFeeTotal(lines []*feesv1.DerivedPostingLine, currency string) *money
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func computeAggregates(base, fee *moneyv1.Money, network *chainv1.EstimateTransferFeeResponse) (*moneyv1.Money, *moneyv1.Money) {
|
func resolveTradeAmounts(intentAmount *moneyv1.Money, fxQuote *oraclev1.Quote, side fxv1.Side) (*moneyv1.Money, *moneyv1.Money) {
|
||||||
if base == nil {
|
if fxQuote == nil {
|
||||||
|
return cloneMoney(intentAmount), cloneMoney(intentAmount)
|
||||||
|
}
|
||||||
|
qSide := fxQuote.GetSide()
|
||||||
|
if qSide == fxv1.Side_SIDE_UNSPECIFIED {
|
||||||
|
qSide = side
|
||||||
|
}
|
||||||
|
|
||||||
|
switch qSide {
|
||||||
|
case fxv1.Side_BUY_BASE_SELL_QUOTE:
|
||||||
|
pay := cloneMoney(fxQuote.GetQuoteAmount())
|
||||||
|
settle := cloneMoney(fxQuote.GetBaseAmount())
|
||||||
|
if pay == nil {
|
||||||
|
pay = cloneMoney(intentAmount)
|
||||||
|
}
|
||||||
|
if settle == nil {
|
||||||
|
settle = cloneMoney(intentAmount)
|
||||||
|
}
|
||||||
|
return pay, settle
|
||||||
|
case fxv1.Side_SELL_BASE_BUY_QUOTE:
|
||||||
|
pay := cloneMoney(fxQuote.GetBaseAmount())
|
||||||
|
settle := cloneMoney(fxQuote.GetQuoteAmount())
|
||||||
|
if pay == nil {
|
||||||
|
pay = cloneMoney(intentAmount)
|
||||||
|
}
|
||||||
|
if settle == nil {
|
||||||
|
settle = cloneMoney(intentAmount)
|
||||||
|
}
|
||||||
|
return pay, settle
|
||||||
|
default:
|
||||||
|
return cloneMoney(intentAmount), cloneMoney(intentAmount)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func computeAggregates(pay, settlement, fee *moneyv1.Money, network *chainv1.EstimateTransferFeeResponse, fxQuote *oraclev1.Quote) (*moneyv1.Money, *moneyv1.Money) {
|
||||||
|
if pay == nil {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
baseDecimal, err := decimalFromMoney(base)
|
debitDecimal, err := decimalFromMoney(pay)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return cloneMoney(base), cloneMoney(base)
|
return cloneMoney(pay), cloneMoney(settlement)
|
||||||
}
|
|
||||||
debit := baseDecimal
|
|
||||||
settlement := baseDecimal
|
|
||||||
|
|
||||||
if feeDecimal, err := decimalFromMoneyMatching(base, fee); err == nil && feeDecimal != nil {
|
|
||||||
debit = debit.Add(*feeDecimal)
|
|
||||||
settlement = settlement.Sub(*feeDecimal)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if network != nil && network.GetNetworkFee() != nil {
|
settlementCurrency := pay.GetCurrency()
|
||||||
if networkDecimal, err := decimalFromMoneyMatching(base, network.GetNetworkFee()); err == nil && networkDecimal != nil {
|
if settlement != nil && strings.TrimSpace(settlement.GetCurrency()) != "" {
|
||||||
debit = debit.Add(*networkDecimal)
|
settlementCurrency = settlement.GetCurrency()
|
||||||
settlement = settlement.Sub(*networkDecimal)
|
}
|
||||||
|
|
||||||
|
settlementDecimal := debitDecimal
|
||||||
|
if settlement != nil {
|
||||||
|
if val, err := decimalFromMoney(settlement); err == nil {
|
||||||
|
settlementDecimal = val
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return makeMoney(base.GetCurrency(), debit), makeMoney(base.GetCurrency(), settlement)
|
adjustDebit := func(m *moneyv1.Money) {
|
||||||
|
converted, err := ensureCurrency(m, pay.GetCurrency(), fxQuote)
|
||||||
|
if err != nil || converted == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if val, err := decimalFromMoney(converted); err == nil {
|
||||||
|
debitDecimal = debitDecimal.Add(val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
adjustSettlement := func(m *moneyv1.Money) {
|
||||||
|
converted, err := ensureCurrency(m, settlementCurrency, fxQuote)
|
||||||
|
if err != nil || converted == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if val, err := decimalFromMoney(converted); err == nil {
|
||||||
|
settlementDecimal = settlementDecimal.Sub(val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
adjustDebit(fee)
|
||||||
|
adjustSettlement(fee)
|
||||||
|
|
||||||
|
if network != nil && network.GetNetworkFee() != nil {
|
||||||
|
adjustDebit(network.GetNetworkFee())
|
||||||
|
adjustSettlement(network.GetNetworkFee())
|
||||||
|
}
|
||||||
|
|
||||||
|
return makeMoney(pay.GetCurrency(), debitDecimal), makeMoney(settlementCurrency, settlementDecimal)
|
||||||
}
|
}
|
||||||
|
|
||||||
func decimalFromMoney(m *moneyv1.Money) (decimal.Decimal, error) {
|
func decimalFromMoney(m *moneyv1.Money) (decimal.Decimal, error) {
|
||||||
@@ -163,6 +225,46 @@ func makeMoney(currency string, value decimal.Decimal) *moneyv1.Money {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ensureCurrency(m *moneyv1.Money, targetCurrency string, quote *oraclev1.Quote) (*moneyv1.Money, error) {
|
||||||
|
if m == nil || strings.TrimSpace(targetCurrency) == "" {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
if strings.EqualFold(m.GetCurrency(), targetCurrency) {
|
||||||
|
return cloneMoney(m), nil
|
||||||
|
}
|
||||||
|
return convertWithQuote(m, quote, targetCurrency)
|
||||||
|
}
|
||||||
|
|
||||||
|
func convertWithQuote(m *moneyv1.Money, quote *oraclev1.Quote, targetCurrency string) (*moneyv1.Money, error) {
|
||||||
|
if m == nil || quote == nil || quote.GetPair() == nil || quote.GetPrice() == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
base := strings.TrimSpace(quote.GetPair().GetBase())
|
||||||
|
qt := strings.TrimSpace(quote.GetPair().GetQuote())
|
||||||
|
if base == "" || qt == "" || strings.TrimSpace(targetCurrency) == "" {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
price, err := decimal.NewFromString(quote.GetPrice().GetValue())
|
||||||
|
if err != nil || price.IsZero() {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
value, err := decimalFromMoney(m)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case strings.EqualFold(m.GetCurrency(), base) && strings.EqualFold(targetCurrency, qt):
|
||||||
|
return makeMoney(targetCurrency, value.Mul(price)), nil
|
||||||
|
case strings.EqualFold(m.GetCurrency(), qt) && strings.EqualFold(targetCurrency, base):
|
||||||
|
return makeMoney(targetCurrency, value.Div(price)), nil
|
||||||
|
default:
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func quoteToProto(src *oracleclient.Quote) *oraclev1.Quote {
|
func quoteToProto(src *oracleclient.Quote) *oraclev1.Quote {
|
||||||
if src == nil {
|
if src == nil {
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -0,0 +1,57 @@
|
|||||||
|
package orchestrator
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
fxv1 "github.com/tech/sendico/pkg/proto/common/fx/v1"
|
||||||
|
moneyv1 "github.com/tech/sendico/pkg/proto/common/money/v1"
|
||||||
|
chainv1 "github.com/tech/sendico/pkg/proto/gateway/chain/v1"
|
||||||
|
oraclev1 "github.com/tech/sendico/pkg/proto/oracle/v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestResolveTradeAmountsBuyBase(t *testing.T) {
|
||||||
|
fxQuote := &oraclev1.Quote{
|
||||||
|
Side: fxv1.Side_BUY_BASE_SELL_QUOTE,
|
||||||
|
Pair: &fxv1.CurrencyPair{Base: "EUR", Quote: "USD"},
|
||||||
|
BaseAmount: &moneyv1.Money{
|
||||||
|
Currency: "EUR",
|
||||||
|
Amount: "100",
|
||||||
|
},
|
||||||
|
QuoteAmount: &moneyv1.Money{
|
||||||
|
Currency: "USD",
|
||||||
|
Amount: "110",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
pay, settle := resolveTradeAmounts(nil, fxQuote, fxv1.Side_SIDE_UNSPECIFIED)
|
||||||
|
if pay.GetCurrency() != "USD" || pay.GetAmount() != "110" {
|
||||||
|
t.Fatalf("expected pay amount in USD 110, got %s %s", pay.GetCurrency(), pay.GetAmount())
|
||||||
|
}
|
||||||
|
if settle.GetCurrency() != "EUR" || settle.GetAmount() != "100" {
|
||||||
|
t.Fatalf("expected settlement in EUR 100, got %s %s", settle.GetCurrency(), settle.GetAmount())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestComputeAggregatesConvertsCurrencies(t *testing.T) {
|
||||||
|
pay := &moneyv1.Money{Currency: "USD", Amount: "100"}
|
||||||
|
settle := &moneyv1.Money{Currency: "EUR", Amount: "50"}
|
||||||
|
fee := &moneyv1.Money{Currency: "USD", Amount: "10"}
|
||||||
|
network := &chainv1.EstimateTransferFeeResponse{
|
||||||
|
NetworkFee: &moneyv1.Money{Currency: "USD", Amount: "5"},
|
||||||
|
}
|
||||||
|
fxQuote := &oraclev1.Quote{
|
||||||
|
Pair: &fxv1.CurrencyPair{Base: "EUR", Quote: "USD"},
|
||||||
|
Side: fxv1.Side_BUY_BASE_SELL_QUOTE,
|
||||||
|
Price: &moneyv1.Decimal{
|
||||||
|
Value: "2",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
debit, settlement := computeAggregates(pay, settle, fee, network, fxQuote)
|
||||||
|
if debit.GetCurrency() != "USD" || debit.GetAmount() != "115" {
|
||||||
|
t.Fatalf("expected debit 115 USD, got %s %s", debit.GetCurrency(), debit.GetAmount())
|
||||||
|
}
|
||||||
|
if settlement.GetCurrency() != "EUR" || settlement.GetAmount() != "42.5" {
|
||||||
|
t.Fatalf("expected settlement 42.5 EUR, got %s %s", settlement.GetCurrency(), settlement.GetAmount())
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
package orchestrator
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
oracleclient "github.com/tech/sendico/fx/oracle/client"
|
||||||
|
fxv1 "github.com/tech/sendico/pkg/proto/common/fx/v1"
|
||||||
|
moneyv1 "github.com/tech/sendico/pkg/proto/common/money/v1"
|
||||||
|
orchestratorv1 "github.com/tech/sendico/pkg/proto/payments/orchestrator/v1"
|
||||||
|
"go.uber.org/zap"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestRequestFXQuoteUsesQuoteAmountWhenCurrencyMatchesQuote(t *testing.T) {
|
||||||
|
ctx := context.Background()
|
||||||
|
var captured oracleclient.GetQuoteParams
|
||||||
|
|
||||||
|
svc := &Service{
|
||||||
|
logger: zap.NewNop(),
|
||||||
|
clock: testClock{now: time.Now()},
|
||||||
|
oracle: oracleDependency{
|
||||||
|
client: &oracleclient.Fake{
|
||||||
|
GetQuoteFn: func(ctx context.Context, params oracleclient.GetQuoteParams) (*oracleclient.Quote, error) {
|
||||||
|
captured = params
|
||||||
|
return &oracleclient.Quote{
|
||||||
|
QuoteRef: "q",
|
||||||
|
Pair: params.Pair,
|
||||||
|
Side: params.Side,
|
||||||
|
Price: "1.1",
|
||||||
|
BaseAmount: params.BaseAmount,
|
||||||
|
QuoteAmount: params.QuoteAmount,
|
||||||
|
ExpiresAt: time.Now(),
|
||||||
|
}, nil
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
req := &orchestratorv1.QuotePaymentRequest{
|
||||||
|
Meta: &orchestratorv1.RequestMeta{OrganizationRef: "org"},
|
||||||
|
Intent: &orchestratorv1.PaymentIntent{
|
||||||
|
Amount: &moneyv1.Money{Currency: "USD", Amount: "100"},
|
||||||
|
Fx: &orchestratorv1.FXIntent{
|
||||||
|
Pair: &fxv1.CurrencyPair{Base: "EUR", Quote: "USD"},
|
||||||
|
Side: fxv1.Side_BUY_BASE_SELL_QUOTE,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := svc.requestFXQuote(ctx, "org", req); err != nil {
|
||||||
|
t.Fatalf("requestFXQuote returned error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if captured.QuoteAmount == nil {
|
||||||
|
t.Fatal("expected quote amount to be populated")
|
||||||
|
}
|
||||||
|
if captured.BaseAmount != nil {
|
||||||
|
t.Fatal("expected base amount to be nil when using quote amount input")
|
||||||
|
}
|
||||||
|
if captured.QuoteAmount.GetCurrency() != "USD" {
|
||||||
|
t.Fatalf("expected quote amount currency USD, got %s", captured.QuoteAmount.GetCurrency())
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -36,8 +36,8 @@ func NewQuotes(logger mlogger.Logger, repo repository.Repository) (*Quotes, erro
|
|||||||
Keys: []ri.Key{{Field: "organizationRef", Sort: ri.Asc}},
|
Keys: []ri.Key{{Field: "organizationRef", Sort: ri.Asc}},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Keys: []ri.Key{{Field: "expiresAt", Sort: ri.Asc}},
|
Keys: []ri.Key{{Field: "expiresAt", Sort: ri.Asc}},
|
||||||
ExpireAfterSeconds: 0,
|
TTL: int32Ptr(0),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,3 +111,7 @@ func (q *Quotes) GetByRef(ctx context.Context, orgRef primitive.ObjectID, quoteR
|
|||||||
}
|
}
|
||||||
|
|
||||||
var _ storage.QuotesStore = (*Quotes)(nil)
|
var _ storage.QuotesStore = (*Quotes)(nil)
|
||||||
|
|
||||||
|
func int32Ptr(v int32) *int32 {
|
||||||
|
return &v
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ module github.com/tech/sendico/pkg
|
|||||||
go 1.24.0
|
go 1.24.0
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/casbin/casbin/v2 v2.134.0
|
github.com/casbin/casbin/v2 v2.135.0
|
||||||
github.com/casbin/mongodb-adapter/v3 v3.7.0
|
github.com/casbin/mongodb-adapter/v3 v3.7.0
|
||||||
github.com/go-chi/chi/v5 v5.2.3
|
github.com/go-chi/chi/v5 v5.2.3
|
||||||
github.com/google/uuid v1.6.0
|
github.com/google/uuid v1.6.0
|
||||||
|
|||||||
@@ -11,8 +11,8 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
|
|||||||
github.com/bmatcuk/doublestar/v4 v4.6.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
|
github.com/bmatcuk/doublestar/v4 v4.6.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
|
||||||
github.com/bmatcuk/doublestar/v4 v4.9.1 h1:X8jg9rRZmJd4yRy7ZeNDRnM+T3ZfHv15JiBJ/avrEXE=
|
github.com/bmatcuk/doublestar/v4 v4.9.1 h1:X8jg9rRZmJd4yRy7ZeNDRnM+T3ZfHv15JiBJ/avrEXE=
|
||||||
github.com/bmatcuk/doublestar/v4 v4.9.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
|
github.com/bmatcuk/doublestar/v4 v4.9.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
|
||||||
github.com/casbin/casbin/v2 v2.134.0 h1:wyO3hZb487GzlGVAI2hUoHQT0ehFD+9B5P+HVG9BVTM=
|
github.com/casbin/casbin/v2 v2.135.0 h1:6BLkMQiGotYyS5yYeWgW19vxqugUlvHFkFiLnLR/bxk=
|
||||||
github.com/casbin/casbin/v2 v2.134.0/go.mod h1:FmcfntdXLTcYXv/hxgNntcRPqAbwOG9xsism0yXT+18=
|
github.com/casbin/casbin/v2 v2.135.0/go.mod h1:FmcfntdXLTcYXv/hxgNntcRPqAbwOG9xsism0yXT+18=
|
||||||
github.com/casbin/govaluate v1.3.0/go.mod h1:G/UnbIjZk/0uMNaLwZZmFQrR72tYRZWQkO70si/iR7A=
|
github.com/casbin/govaluate v1.3.0/go.mod h1:G/UnbIjZk/0uMNaLwZZmFQrR72tYRZWQkO70si/iR7A=
|
||||||
github.com/casbin/govaluate v1.10.0 h1:ffGw51/hYH3w3rZcxO/KcaUIDOLP84w7nsidMVgaDG0=
|
github.com/casbin/govaluate v1.10.0 h1:ffGw51/hYH3w3rZcxO/KcaUIDOLP84w7nsidMVgaDG0=
|
||||||
github.com/casbin/govaluate v1.10.0/go.mod h1:G/UnbIjZk/0uMNaLwZZmFQrR72tYRZWQkO70si/iR7A=
|
github.com/casbin/govaluate v1.10.0/go.mod h1:G/UnbIjZk/0uMNaLwZZmFQrR72tYRZWQkO70si/iR7A=
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ require (
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/bmatcuk/doublestar/v4 v4.9.1 // indirect
|
github.com/bmatcuk/doublestar/v4 v4.9.1 // indirect
|
||||||
github.com/casbin/casbin/v2 v2.134.0 // indirect
|
github.com/casbin/casbin/v2 v2.135.0 // indirect
|
||||||
github.com/casbin/govaluate v1.10.0 // indirect
|
github.com/casbin/govaluate v1.10.0 // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -50,8 +50,8 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
|
|||||||
github.com/bmatcuk/doublestar/v4 v4.6.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
|
github.com/bmatcuk/doublestar/v4 v4.6.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
|
||||||
github.com/bmatcuk/doublestar/v4 v4.9.1 h1:X8jg9rRZmJd4yRy7ZeNDRnM+T3ZfHv15JiBJ/avrEXE=
|
github.com/bmatcuk/doublestar/v4 v4.9.1 h1:X8jg9rRZmJd4yRy7ZeNDRnM+T3ZfHv15JiBJ/avrEXE=
|
||||||
github.com/bmatcuk/doublestar/v4 v4.9.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
|
github.com/bmatcuk/doublestar/v4 v4.9.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
|
||||||
github.com/casbin/casbin/v2 v2.134.0 h1:wyO3hZb487GzlGVAI2hUoHQT0ehFD+9B5P+HVG9BVTM=
|
github.com/casbin/casbin/v2 v2.135.0 h1:6BLkMQiGotYyS5yYeWgW19vxqugUlvHFkFiLnLR/bxk=
|
||||||
github.com/casbin/casbin/v2 v2.134.0/go.mod h1:FmcfntdXLTcYXv/hxgNntcRPqAbwOG9xsism0yXT+18=
|
github.com/casbin/casbin/v2 v2.135.0/go.mod h1:FmcfntdXLTcYXv/hxgNntcRPqAbwOG9xsism0yXT+18=
|
||||||
github.com/casbin/govaluate v1.3.0/go.mod h1:G/UnbIjZk/0uMNaLwZZmFQrR72tYRZWQkO70si/iR7A=
|
github.com/casbin/govaluate v1.3.0/go.mod h1:G/UnbIjZk/0uMNaLwZZmFQrR72tYRZWQkO70si/iR7A=
|
||||||
github.com/casbin/govaluate v1.10.0 h1:ffGw51/hYH3w3rZcxO/KcaUIDOLP84w7nsidMVgaDG0=
|
github.com/casbin/govaluate v1.10.0 h1:ffGw51/hYH3w3rZcxO/KcaUIDOLP84w7nsidMVgaDG0=
|
||||||
github.com/casbin/govaluate v1.10.0/go.mod h1:G/UnbIjZk/0uMNaLwZZmFQrR72tYRZWQkO70si/iR7A=
|
github.com/casbin/govaluate v1.10.0/go.mod h1:G/UnbIjZk/0uMNaLwZZmFQrR72tYRZWQkO70si/iR7A=
|
||||||
|
|||||||
@@ -2,14 +2,14 @@ package srequest
|
|||||||
|
|
||||||
import orchestratorv1 "github.com/tech/sendico/pkg/proto/payments/orchestrator/v1"
|
import orchestratorv1 "github.com/tech/sendico/pkg/proto/payments/orchestrator/v1"
|
||||||
|
|
||||||
type QuotePaymentPayload struct {
|
type QuotePayment struct {
|
||||||
IdempotencyKey string `json:"idempotencyKey"`
|
IdempotencyKey string `json:"idempotencyKey"`
|
||||||
Intent *orchestratorv1.PaymentIntent `json:"intent"`
|
Intent *orchestratorv1.PaymentIntent `json:"intent"`
|
||||||
PreviewOnly bool `json:"previewOnly"`
|
PreviewOnly bool `json:"previewOnly"`
|
||||||
Metadata map[string]string `json:"metadata,omitempty"`
|
Metadata map[string]string `json:"metadata,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type InitiatePaymentPayload struct {
|
type InitiatePayment struct {
|
||||||
IdempotencyKey string `json:"idempotencyKey"`
|
IdempotencyKey string `json:"idempotencyKey"`
|
||||||
Intent *orchestratorv1.PaymentIntent `json:"intent"`
|
Intent *orchestratorv1.PaymentIntent `json:"intent"`
|
||||||
Metadata map[string]string `json:"metadata,omitempty"`
|
Metadata map[string]string `json:"metadata,omitempty"`
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import (
|
|||||||
"github.com/tech/sendico/pkg/mservice"
|
"github.com/tech/sendico/pkg/mservice"
|
||||||
ledgerv1 "github.com/tech/sendico/pkg/proto/ledger/v1"
|
ledgerv1 "github.com/tech/sendico/pkg/proto/ledger/v1"
|
||||||
"github.com/tech/sendico/server/interface/api/sresponse"
|
"github.com/tech/sendico/server/interface/api/sresponse"
|
||||||
|
mutil "github.com/tech/sendico/server/internal/mutil/param"
|
||||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
@@ -29,11 +30,11 @@ func (a *LedgerAPI) getBalance(r *http.Request, account *model.Account, token *s
|
|||||||
ctx := r.Context()
|
ctx := r.Context()
|
||||||
res, err := a.enf.Enforce(ctx, a.balancePerm, account.ID, orgRef, primitive.NilObjectID, model.ActionRead)
|
res, err := a.enf.Enforce(ctx, a.balancePerm, account.ID, orgRef, primitive.NilObjectID, model.ActionRead)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.logger.Warn("Failed to check ledger balance access permissions", zap.Error(err), zap.String(a.oph.Name(), orgRef.Hex()), zap.String("ledger_account_ref", accountRef))
|
a.logger.Warn("Failed to check ledger balance access permissions", zap.Error(err), mutil.PLog(a.oph, r), zap.String("ledger_account_ref", accountRef))
|
||||||
return response.Auto(a.logger, a.Name(), err)
|
return response.Auto(a.logger, a.Name(), err)
|
||||||
}
|
}
|
||||||
if !res {
|
if !res {
|
||||||
a.logger.Debug("Access denied when reading ledger balance", zap.String(a.oph.Name(), orgRef.Hex()), zap.String("ledger_account_ref", accountRef))
|
a.logger.Debug("Access denied when reading ledger balance", mutil.PLog(a.oph, r), zap.String("ledger_account_ref", accountRef))
|
||||||
return response.AccessDenied(a.logger, a.Name(), "ledger balance read permission denied")
|
return response.AccessDenied(a.logger, a.Name(), "ledger balance read permission denied")
|
||||||
}
|
}
|
||||||
if a.client == nil {
|
if a.client == nil {
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
"github.com/tech/sendico/pkg/mservice"
|
"github.com/tech/sendico/pkg/mservice"
|
||||||
ledgerv1 "github.com/tech/sendico/pkg/proto/ledger/v1"
|
ledgerv1 "github.com/tech/sendico/pkg/proto/ledger/v1"
|
||||||
"github.com/tech/sendico/server/interface/api/sresponse"
|
"github.com/tech/sendico/server/interface/api/sresponse"
|
||||||
|
mutil "github.com/tech/sendico/server/internal/mutil/param"
|
||||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
@@ -23,11 +24,11 @@ func (a *LedgerAPI) listAccounts(r *http.Request, account *model.Account, token
|
|||||||
ctx := r.Context()
|
ctx := r.Context()
|
||||||
res, err := a.enf.Enforce(ctx, a.permissionRef, account.ID, orgRef, primitive.NilObjectID, model.ActionRead)
|
res, err := a.enf.Enforce(ctx, a.permissionRef, account.ID, orgRef, primitive.NilObjectID, model.ActionRead)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.logger.Warn("Failed to check ledger accounts access permissions", zap.Error(err), zap.String(a.oph.Name(), orgRef.Hex()))
|
a.logger.Warn("Failed to check ledger accounts access permissions", zap.Error(err), mutil.PLog(a.oph, r))
|
||||||
return response.Auto(a.logger, a.Name(), err)
|
return response.Auto(a.logger, a.Name(), err)
|
||||||
}
|
}
|
||||||
if !res {
|
if !res {
|
||||||
a.logger.Debug("Access denied when listing ledger accounts", zap.String(a.oph.Name(), orgRef.Hex()))
|
a.logger.Debug("Access denied when listing ledger accounts", mutil.PLog(a.oph, r))
|
||||||
return response.AccessDenied(a.logger, a.Name(), "ledger accounts read permission denied")
|
return response.AccessDenied(a.logger, a.Name(), "ledger accounts read permission denied")
|
||||||
}
|
}
|
||||||
if a.client == nil {
|
if a.client == nil {
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import (
|
|||||||
orchestratorv1 "github.com/tech/sendico/pkg/proto/payments/orchestrator/v1"
|
orchestratorv1 "github.com/tech/sendico/pkg/proto/payments/orchestrator/v1"
|
||||||
"github.com/tech/sendico/server/interface/api/srequest"
|
"github.com/tech/sendico/server/interface/api/srequest"
|
||||||
"github.com/tech/sendico/server/interface/api/sresponse"
|
"github.com/tech/sendico/server/interface/api/sresponse"
|
||||||
|
mutil "github.com/tech/sendico/server/internal/mutil/param"
|
||||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
@@ -26,11 +27,11 @@ func (a *PaymentAPI) initiatePayment(r *http.Request, account *model.Account, to
|
|||||||
ctx := r.Context()
|
ctx := r.Context()
|
||||||
allowed, err := a.enf.Enforce(ctx, a.permissionRef, account.ID, orgRef, primitive.NilObjectID, model.ActionCreate)
|
allowed, err := a.enf.Enforce(ctx, a.permissionRef, account.ID, orgRef, primitive.NilObjectID, model.ActionCreate)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.logger.Warn("Failed to check payments access permissions", zap.Error(err), zap.String(a.oph.Name(), orgRef.Hex()))
|
a.logger.Warn("Failed to check payments access permissions", zap.Error(err), mutil.PLog(a.oph, r))
|
||||||
return response.Auto(a.logger, a.Name(), err)
|
return response.Auto(a.logger, a.Name(), err)
|
||||||
}
|
}
|
||||||
if !allowed {
|
if !allowed {
|
||||||
a.logger.Debug("Access denied when initiating payment", zap.String(a.oph.Name(), orgRef.Hex()))
|
a.logger.Debug("Access denied when initiating payment", mutil.PLog(a.oph, r))
|
||||||
return response.AccessDenied(a.logger, a.Name(), "payments write permission denied")
|
return response.AccessDenied(a.logger, a.Name(), "payments write permission denied")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,10 +67,10 @@ func (a *PaymentAPI) initiatePayment(r *http.Request, account *model.Account, to
|
|||||||
return sresponse.PaymentResponse(a.logger, resp.GetPayment(), token)
|
return sresponse.PaymentResponse(a.logger, resp.GetPayment(), token)
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeInitiatePayload(r *http.Request) (*srequest.InitiatePaymentPayload, error) {
|
func decodeInitiatePayload(r *http.Request) (*srequest.InitiatePayment, error) {
|
||||||
defer r.Body.Close()
|
defer r.Body.Close()
|
||||||
|
|
||||||
payload := &srequest.InitiatePaymentPayload{}
|
payload := &srequest.InitiatePayment{}
|
||||||
if err := json.NewDecoder(r.Body).Decode(payload); err != nil {
|
if err := json.NewDecoder(r.Body).Decode(payload); err != nil {
|
||||||
return nil, merrors.InvalidArgument("invalid payload: " + err.Error())
|
return nil, merrors.InvalidArgument("invalid payload: " + err.Error())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import (
|
|||||||
orchestratorv1 "github.com/tech/sendico/pkg/proto/payments/orchestrator/v1"
|
orchestratorv1 "github.com/tech/sendico/pkg/proto/payments/orchestrator/v1"
|
||||||
"github.com/tech/sendico/server/interface/api/srequest"
|
"github.com/tech/sendico/server/interface/api/srequest"
|
||||||
"github.com/tech/sendico/server/interface/api/sresponse"
|
"github.com/tech/sendico/server/interface/api/sresponse"
|
||||||
|
mutil "github.com/tech/sendico/server/internal/mutil/param"
|
||||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
@@ -25,11 +26,11 @@ func (a *PaymentAPI) quotePayment(r *http.Request, account *model.Account, token
|
|||||||
ctx := r.Context()
|
ctx := r.Context()
|
||||||
allowed, err := a.enf.Enforce(ctx, a.permissionRef, account.ID, orgRef, primitive.NilObjectID, model.ActionCreate)
|
allowed, err := a.enf.Enforce(ctx, a.permissionRef, account.ID, orgRef, primitive.NilObjectID, model.ActionCreate)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.logger.Warn("Failed to check payments access permissions", zap.Error(err), zap.String(a.oph.Name(), orgRef.Hex()))
|
a.logger.Warn("Failed to check payments access permissions", zap.Error(err), mutil.PLog(a.oph, r))
|
||||||
return response.Auto(a.logger, a.Name(), err)
|
return response.Auto(a.logger, a.Name(), err)
|
||||||
}
|
}
|
||||||
if !allowed {
|
if !allowed {
|
||||||
a.logger.Debug("Access denied when quoting payment", zap.String(a.oph.Name(), orgRef.Hex()))
|
a.logger.Debug("Access denied when quoting payment", mutil.PLog(a.oph, r))
|
||||||
return response.AccessDenied(a.logger, a.Name(), "payments write permission denied")
|
return response.AccessDenied(a.logger, a.Name(), "payments write permission denied")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,10 +57,10 @@ func (a *PaymentAPI) quotePayment(r *http.Request, account *model.Account, token
|
|||||||
return sresponse.PaymentQuoteResponse(a.logger, resp.GetQuote(), token)
|
return sresponse.PaymentQuoteResponse(a.logger, resp.GetQuote(), token)
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeQuotePayload(r *http.Request) (*srequest.QuotePaymentPayload, error) {
|
func decodeQuotePayload(r *http.Request) (*srequest.QuotePayment, error) {
|
||||||
defer r.Body.Close()
|
defer r.Body.Close()
|
||||||
|
|
||||||
payload := &srequest.QuotePaymentPayload{}
|
payload := &srequest.QuotePayment{}
|
||||||
if err := json.NewDecoder(r.Body).Decode(payload); err != nil {
|
if err := json.NewDecoder(r.Body).Decode(payload); err != nil {
|
||||||
return nil, merrors.InvalidArgument("invalid payload: " + err.Error())
|
return nil, merrors.InvalidArgument("invalid payload: " + err.Error())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import (
|
|||||||
"github.com/tech/sendico/pkg/mservice"
|
"github.com/tech/sendico/pkg/mservice"
|
||||||
chainv1 "github.com/tech/sendico/pkg/proto/gateway/chain/v1"
|
chainv1 "github.com/tech/sendico/pkg/proto/gateway/chain/v1"
|
||||||
"github.com/tech/sendico/server/interface/api/sresponse"
|
"github.com/tech/sendico/server/interface/api/sresponse"
|
||||||
|
mutil "github.com/tech/sendico/server/internal/mutil/param"
|
||||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
@@ -28,11 +29,11 @@ func (a *WalletAPI) getWalletBalance(r *http.Request, account *model.Account, to
|
|||||||
ctx := r.Context()
|
ctx := r.Context()
|
||||||
res, err := a.enf.Enforce(ctx, a.balancesPermissionRef, account.ID, orgRef, primitive.NilObjectID, model.ActionRead)
|
res, err := a.enf.Enforce(ctx, a.balancesPermissionRef, account.ID, orgRef, primitive.NilObjectID, model.ActionRead)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.logger.Warn("Failed to check wallet balance permissions", zap.Error(err), zap.String(a.oph.Name(), orgRef.Hex()), zap.String("wallet_ref", walletRef))
|
a.logger.Warn("Failed to check wallet balance permissions", zap.Error(err), mutil.PLog(a.oph, r), zap.String("wallet_ref", walletRef))
|
||||||
return response.Auto(a.logger, a.Name(), err)
|
return response.Auto(a.logger, a.Name(), err)
|
||||||
}
|
}
|
||||||
if !res {
|
if !res {
|
||||||
a.logger.Debug("Access denied when reading wallet balance", zap.String(a.oph.Name(), orgRef.Hex()), zap.String("wallet_ref", walletRef))
|
a.logger.Debug("Access denied when reading wallet balance", mutil.PLog(a.oph, r), zap.String("wallet_ref", walletRef))
|
||||||
return response.AccessDenied(a.logger, a.Name(), "wallet balance read permission denied")
|
return response.AccessDenied(a.logger, a.Name(), "wallet balance read permission denied")
|
||||||
}
|
}
|
||||||
if a.chainGateway == nil {
|
if a.chainGateway == nil {
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import (
|
|||||||
"github.com/tech/sendico/pkg/mservice"
|
"github.com/tech/sendico/pkg/mservice"
|
||||||
chainv1 "github.com/tech/sendico/pkg/proto/gateway/chain/v1"
|
chainv1 "github.com/tech/sendico/pkg/proto/gateway/chain/v1"
|
||||||
"github.com/tech/sendico/server/interface/api/sresponse"
|
"github.com/tech/sendico/server/interface/api/sresponse"
|
||||||
|
mutil "github.com/tech/sendico/server/internal/mutil/param"
|
||||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
@@ -24,11 +25,11 @@ func (a *WalletAPI) listWallets(r *http.Request, account *model.Account, token *
|
|||||||
ctx := r.Context()
|
ctx := r.Context()
|
||||||
res, err := a.enf.Enforce(ctx, a.walletsPermissionRef, account.ID, orgRef, primitive.NilObjectID, model.ActionRead)
|
res, err := a.enf.Enforce(ctx, a.walletsPermissionRef, account.ID, orgRef, primitive.NilObjectID, model.ActionRead)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.logger.Warn("Failed to check chain wallet access permissions", zap.Error(err), zap.String(a.oph.Name(), orgRef.Hex()))
|
a.logger.Warn("Failed to check chain wallet access permissions", zap.Error(err), mutil.PLog(a.oph, r))
|
||||||
return response.Auto(a.logger, a.Name(), err)
|
return response.Auto(a.logger, a.Name(), err)
|
||||||
}
|
}
|
||||||
if !res {
|
if !res {
|
||||||
a.logger.Debug("Access denied when listing organization wallets", zap.String(a.oph.Name(), orgRef.Hex()))
|
a.logger.Debug("Access denied when listing organization wallets", mutil.PLog(a.oph, r))
|
||||||
return response.AccessDenied(a.logger, a.Name(), "wallets read permission denied")
|
return response.AccessDenied(a.logger, a.Name(), "wallets read permission denied")
|
||||||
}
|
}
|
||||||
if a.chainGateway == nil {
|
if a.chainGateway == nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user