mirror of
https://github.com/emo2007/block-accounting.git
synced 2025-01-18 07:26:27 +00:00
invite link gen implemented
This commit is contained in:
parent
2ab2cf61ed
commit
a97a2cdf19
@ -16,4 +16,4 @@ RUN go build -ldflags="-s -w" -o /app/blockd cmd/main.go
|
||||
|
||||
EXPOSE 8080
|
||||
|
||||
CMD ["/app/blockd", "-log-level=debug","-log-local=false","-log-add-source=true","-rest-address=0.0.0.0:8080","-db-host=blockd-db:5432","-db-database=blockd","-db-user=blockd","-db-secret=blockd","-db-enable-tls=false"]
|
||||
CMD ["/app/blockd", "-log-level=info","-log-local=false","-log-add-source=true","-rest-address=0.0.0.0:8080","-db-host=blockd-db:5432","-db-database=blockd","-db-user=blockd","-db-secret=blockd","-db-enable-tls=false", "-cache-host=blockd-cache:6379"]
|
||||
|
@ -2,7 +2,6 @@ package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
@ -117,8 +116,6 @@ func main() {
|
||||
},
|
||||
}
|
||||
|
||||
fmt.Println(config)
|
||||
|
||||
service, cleanup, err := factory.ProvideService(config)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
|
@ -17,15 +17,13 @@ services:
|
||||
context: .
|
||||
dockerfile: ./Dockerfile
|
||||
ports:
|
||||
- 8080:8080
|
||||
- 8081:8080
|
||||
networks:
|
||||
- blockd-net
|
||||
- syslog
|
||||
depends_on:
|
||||
blockd-db:
|
||||
condition: service_healthy
|
||||
syslog:
|
||||
condition: service_started
|
||||
profiles: [blockd]
|
||||
|
||||
blockd-db:
|
||||
@ -61,52 +59,53 @@ services:
|
||||
- 6379:6379
|
||||
profiles: [blockd, database, noback]
|
||||
|
||||
# prometheus:
|
||||
# image: prom/prometheus
|
||||
# container_name: prometheus
|
||||
# command:
|
||||
# - '--config.file=/etc/prometheus/prometheus.yml'
|
||||
# ports:
|
||||
# - 9091:9090
|
||||
# restart: unless-stopped
|
||||
# networks:
|
||||
# - blockd-net
|
||||
# volumes:
|
||||
# - ./prometheus:/etc/prometheus
|
||||
# - prometheus_data:/prometheus
|
||||
# profiles: [blockd, metrics, noback]
|
||||
prometheus:
|
||||
image: prom/prometheus
|
||||
container_name: prometheus
|
||||
command:
|
||||
- '--config.file=/etc/prometheus/prometheus.yml'
|
||||
ports:
|
||||
- 9091:9090
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- blockd-net
|
||||
volumes:
|
||||
- ./prometheus:/etc/prometheus
|
||||
- prometheus_data:/prometheus
|
||||
profiles: [metrics]
|
||||
|
||||
# grafana:
|
||||
# image: grafana/grafana
|
||||
# container_name: grafana
|
||||
# ports:
|
||||
# - 3112:3000
|
||||
# restart: unless-stopped
|
||||
# networks:
|
||||
# - blockd-net
|
||||
# environment:
|
||||
# - GF_SECURITY_ADMIN_USER=admin
|
||||
# - GF_SECURITY_ADMIN_PASSWORD=grafana
|
||||
# volumes:
|
||||
# - ./grafana:/etc/grafana/provisioning/datasources
|
||||
# profiles: [blockd, metrics, noback]
|
||||
grafana:
|
||||
image: grafana/grafana
|
||||
container_name: grafana
|
||||
ports:
|
||||
- 3112:3000
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- blockd-net
|
||||
environment:
|
||||
- GF_SECURITY_ADMIN_USER=admin
|
||||
- GF_SECURITY_ADMIN_PASSWORD=grafana
|
||||
volumes:
|
||||
- ./grafana:/etc/grafana/provisioning/datasources
|
||||
profiles: [metrics]
|
||||
|
||||
# syslog:
|
||||
# image: linuxserver/syslog-ng:3.36.1
|
||||
# container_name: syslog-ng
|
||||
# environment:
|
||||
# - PUID=0
|
||||
# - PGID=0
|
||||
# - TZ=UTC
|
||||
# volumes:
|
||||
# - /srv/syslog/config:/config
|
||||
# - /srv/syslog/logs:/var/log
|
||||
# ports:
|
||||
# - 514:5514/udp
|
||||
# - 601:6601/tcp
|
||||
# - 6514:6514/tcp
|
||||
# restart: unless-stopped
|
||||
# networks:
|
||||
# - syslog
|
||||
# logging:
|
||||
# driver: "json-file"
|
||||
syslog:
|
||||
image: linuxserver/syslog-ng:3.36.1
|
||||
container_name: syslog-ng
|
||||
environment:
|
||||
- PUID=0
|
||||
- PGID=0
|
||||
- TZ=UTC
|
||||
volumes:
|
||||
- /srv/syslog/config:/config
|
||||
- /srv/syslog/logs:/var/log
|
||||
ports:
|
||||
- 514:5514/udp
|
||||
- 601:6601/tcp
|
||||
- 6514:6514/tcp
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- syslog
|
||||
logging:
|
||||
driver: "json-file"
|
||||
profiles: [metrics]
|
||||
|
@ -16,6 +16,7 @@ import (
|
||||
"github.com/emochka2007/block-accounting/internal/usecase/interactors/organizations"
|
||||
"github.com/emochka2007/block-accounting/internal/usecase/interactors/transactions"
|
||||
"github.com/emochka2007/block-accounting/internal/usecase/interactors/users"
|
||||
"github.com/emochka2007/block-accounting/internal/usecase/repository/auth"
|
||||
)
|
||||
|
||||
var interfaceSet wire.ProviderSet = wire.NewSet(
|
||||
@ -67,12 +68,14 @@ func provideAuthController(
|
||||
usersInteractor users.UsersInteractor,
|
||||
authPresenter presenters.AuthPresenter,
|
||||
jwtInteractor jwt.JWTInteractor,
|
||||
repo auth.Repository,
|
||||
) controllers.AuthController {
|
||||
return controllers.NewAuthController(
|
||||
log.WithGroup("auth-controller"),
|
||||
authPresenter,
|
||||
usersInteractor,
|
||||
jwtInteractor,
|
||||
repo,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -27,7 +27,7 @@ func ProvideService(c config.Config) (service.Service, func(), error) {
|
||||
authRepository := provideAuthRepository(db)
|
||||
jwtInteractor := provideJWTInteractor(c, usersInteractor, authRepository)
|
||||
authPresenter := provideAuthPresenter(jwtInteractor)
|
||||
authController := provideAuthController(logger, usersInteractor, authPresenter, jwtInteractor)
|
||||
authController := provideAuthController(logger, usersInteractor, authPresenter, jwtInteractor, authRepository)
|
||||
organizationsRepository := provideOrganizationsRepository(db, usersRepository)
|
||||
client, cleanup2 := provideRedisConnection(c)
|
||||
cache := provideRedisCache(client, logger)
|
||||
|
@ -2,18 +2,23 @@ package controllers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/emochka2007/block-accounting/internal/interface/rest/domain"
|
||||
"github.com/emochka2007/block-accounting/internal/interface/rest/presenters"
|
||||
"github.com/emochka2007/block-accounting/internal/pkg/bip39"
|
||||
"github.com/emochka2007/block-accounting/internal/pkg/ctxmeta"
|
||||
"github.com/emochka2007/block-accounting/internal/pkg/hdwallet"
|
||||
"github.com/emochka2007/block-accounting/internal/usecase/interactors/jwt"
|
||||
"github.com/emochka2007/block-accounting/internal/usecase/interactors/users"
|
||||
"github.com/emochka2007/block-accounting/internal/usecase/repository/auth"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -34,6 +39,7 @@ type authController struct {
|
||||
presenter presenters.AuthPresenter
|
||||
usersInteractor users.UsersInteractor
|
||||
jwtInteractor jwt.JWTInteractor
|
||||
repo auth.Repository
|
||||
}
|
||||
|
||||
func NewAuthController(
|
||||
@ -41,12 +47,14 @@ func NewAuthController(
|
||||
presenter presenters.AuthPresenter,
|
||||
usersInteractor users.UsersInteractor,
|
||||
jwtInteractor jwt.JWTInteractor,
|
||||
repo auth.Repository,
|
||||
) AuthController {
|
||||
return &authController{
|
||||
log: log,
|
||||
presenter: presenter,
|
||||
usersInteractor: usersInteractor,
|
||||
jwtInteractor: jwtInteractor,
|
||||
repo: repo,
|
||||
}
|
||||
}
|
||||
|
||||
@ -140,9 +148,64 @@ func (c *authController) Refresh(w http.ResponseWriter, req *http.Request) ([]by
|
||||
|
||||
// const mnemonicEntropyBitSize int = 256
|
||||
|
||||
func (c *authController) Invite(w http.ResponseWriter, req *http.Request) ([]byte, error) {
|
||||
func (c *authController) Invite(w http.ResponseWriter, r *http.Request) ([]byte, error) {
|
||||
request, err := presenters.CreateRequest[domain.NewInviteLinkRequest](r)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error create refresh request. %w", err)
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
organizationID, err := ctxmeta.OrganizationId(r.Context())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error fetch organization id from context. %w", err)
|
||||
}
|
||||
|
||||
user, err := ctxmeta.User(r.Context())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error fetch user from context. %w", err)
|
||||
}
|
||||
|
||||
c.log.Debug(
|
||||
"invite request",
|
||||
slog.Int("exp at", request.ExpirationDate),
|
||||
slog.String("org id", organizationID.String()),
|
||||
slog.String("inviter id", user.Id().String()),
|
||||
)
|
||||
|
||||
ctx, cancel := context.WithTimeout(r.Context(), 3*time.Second)
|
||||
defer cancel()
|
||||
|
||||
linkHash := sha256.New()
|
||||
|
||||
linkHash.Write([]byte(
|
||||
user.Id().String() + organizationID.String() + time.Now().String(),
|
||||
))
|
||||
|
||||
linkHashString := strings.ReplaceAll(
|
||||
strings.ReplaceAll(
|
||||
strings.ReplaceAll(
|
||||
base64.StdEncoding.EncodeToString(linkHash.Sum(nil)),
|
||||
"/", "%",
|
||||
),
|
||||
"?", "@",
|
||||
),
|
||||
"&", "#",
|
||||
)
|
||||
|
||||
c.log.Debug(
|
||||
"",
|
||||
slog.String("link", linkHashString),
|
||||
)
|
||||
|
||||
if err := c.repo.AddInvite(ctx, auth.AddInviteParams{
|
||||
LinkHash: linkHashString,
|
||||
CreatedBy: *user,
|
||||
CreatedAt: time.Now(),
|
||||
ExpiredAt: time.UnixMilli(int64(request.ExpirationDate)),
|
||||
}); err != nil {
|
||||
return nil, fmt.Errorf("error add new invite link. %w", err)
|
||||
}
|
||||
|
||||
return c.presenter.ResponseNewInvite(ctx, organizationID, linkHashString)
|
||||
}
|
||||
|
||||
func (c *authController) JoinWithInvite(w http.ResponseWriter, req *http.Request) ([]byte, error) {
|
||||
|
@ -112,7 +112,11 @@ type NewMultisigRequest struct {
|
||||
Owners []struct {
|
||||
PublicKey string `json:"public_key"`
|
||||
} `json:"owners"`
|
||||
Confirmations int `json:confirmations`
|
||||
Confirmations int `json:"confirmations"`
|
||||
}
|
||||
|
||||
type NewInviteLinkRequest struct {
|
||||
ExpirationDate int `json:"expiration_date"`
|
||||
}
|
||||
|
||||
func BuildRequest[T any](data []byte) (*T, error) {
|
||||
|
@ -1,6 +1,7 @@
|
||||
package presenters
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"time"
|
||||
@ -8,12 +9,18 @@ import (
|
||||
"github.com/emochka2007/block-accounting/internal/interface/rest/domain"
|
||||
"github.com/emochka2007/block-accounting/internal/pkg/models"
|
||||
"github.com/emochka2007/block-accounting/internal/usecase/interactors/jwt"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type AuthPresenter interface {
|
||||
ResponseJoin(user *models.User) ([]byte, error)
|
||||
ResponseLogin(user *models.User) ([]byte, error)
|
||||
ResponseRefresh(tokens jwt.AccessToken) ([]byte, error)
|
||||
ResponseNewInvite(
|
||||
ctx context.Context,
|
||||
organizationID uuid.UUID,
|
||||
link string,
|
||||
) ([]byte, error)
|
||||
}
|
||||
|
||||
type authPresenter struct {
|
||||
@ -79,3 +86,18 @@ func (p *authPresenter) ResponseRefresh(tokens jwt.AccessToken) ([]byte, error)
|
||||
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (p *authPresenter) ResponseNewInvite(
|
||||
ctx context.Context,
|
||||
organizationID uuid.UUID,
|
||||
link string,
|
||||
) ([]byte, error) {
|
||||
out, err := json.Marshal(map[string]string{
|
||||
"link": "/" + organizationID.String() + "/invite/" + link,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error marshal refresh response. %w", err)
|
||||
}
|
||||
|
||||
return out, nil
|
||||
}
|
||||
|
@ -12,6 +12,8 @@ type Multisig struct {
|
||||
OrganizationID uuid.UUID
|
||||
Owners []OrganizationParticipant
|
||||
ConfirmationsRequired int
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
}
|
||||
|
||||
type MultisigConfirmation struct {
|
||||
|
7
backend/internal/usecase/repository/auth/errors.go
Normal file
7
backend/internal/usecase/repository/auth/errors.go
Normal file
@ -0,0 +1,7 @@
|
||||
package auth
|
||||
|
||||
import "errors"
|
||||
|
||||
var (
|
||||
ErrorInviteLinkExpired = errors.New("invite link expired")
|
||||
)
|
@ -8,6 +8,7 @@ import (
|
||||
"time"
|
||||
|
||||
sq "github.com/Masterminds/squirrel"
|
||||
"github.com/emochka2007/block-accounting/internal/pkg/models"
|
||||
sqltools "github.com/emochka2007/block-accounting/internal/pkg/sqlutils"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
@ -60,6 +61,9 @@ type Repository interface {
|
||||
AddToken(ctx context.Context, params AddTokenParams) error
|
||||
GetTokens(ctx context.Context, params GetTokenParams) (*AccessToken, error)
|
||||
RefreshToken(ctx context.Context, params RefreshTokenParams) error
|
||||
|
||||
AddInvite(ctx context.Context, params AddInviteParams) error
|
||||
MarkAsUsedLink(ctx context.Context, linkHash string, usedAt time.Time) error
|
||||
}
|
||||
|
||||
type repositorySQL struct {
|
||||
@ -180,6 +184,70 @@ func (r *repositorySQL) GetTokens(ctx context.Context, params GetTokenParams) (*
|
||||
return token, nil
|
||||
}
|
||||
|
||||
type AddInviteParams struct {
|
||||
LinkHash string
|
||||
CreatedBy models.User
|
||||
CreatedAt time.Time
|
||||
ExpiredAt time.Time
|
||||
}
|
||||
|
||||
func (r *repositorySQL) AddInvite(
|
||||
ctx context.Context,
|
||||
params AddInviteParams,
|
||||
) error {
|
||||
return sqltools.Transaction(ctx, r.db, func(ctx context.Context) error {
|
||||
query := sq.Insert("invites").Columns(
|
||||
"link_hash",
|
||||
"created_by",
|
||||
"created_at",
|
||||
"expired_at",
|
||||
).Values(
|
||||
params.LinkHash,
|
||||
params.CreatedBy.Id(),
|
||||
params.CreatedAt,
|
||||
params.ExpiredAt,
|
||||
).PlaceholderFormat(sq.Dollar)
|
||||
|
||||
if _, err := query.RunWith(r.Conn(ctx)).ExecContext(ctx); err != nil {
|
||||
return fmt.Errorf("error add invite link. %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (r *repositorySQL) MarkAsUsedLink(
|
||||
ctx context.Context,
|
||||
linkHash string,
|
||||
usedAt time.Time,
|
||||
) error {
|
||||
return sqltools.Transaction(ctx, r.db, func(ctx context.Context) error {
|
||||
query := sq.Select("expired_at").From("invites").Where(sq.Eq{
|
||||
"link_hash": linkHash,
|
||||
}).Limit(1).PlaceholderFormat(sq.Dollar)
|
||||
|
||||
var expAt time.Time
|
||||
|
||||
if err := query.RunWith(r.Conn(ctx)).QueryRowContext(ctx).Scan(&expAt); err != nil {
|
||||
return fmt.Errorf("error fetch expiration date from database. %w", err)
|
||||
}
|
||||
|
||||
if expAt.After(time.Now()) {
|
||||
return ErrorInviteLinkExpired
|
||||
}
|
||||
|
||||
updateQuery := sq.Update("invites").SetMap(sq.Eq{
|
||||
"used_at": usedAt,
|
||||
})
|
||||
|
||||
if _, err := updateQuery.RunWith(r.Conn(ctx)).ExecContext(ctx); err != nil {
|
||||
return fmt.Errorf("error add invite link. %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func NewRepository(db *sql.DB) Repository {
|
||||
return &repositorySQL{
|
||||
db: db,
|
||||
|
@ -20,8 +20,6 @@ func ProvideDatabaseConnection(c config.Config) (*sql.DB, func(), error) {
|
||||
c.DB.User, c.DB.Secret, c.DB.Host, c.DB.Database, sslmode,
|
||||
)
|
||||
|
||||
fmt.Println(connStr)
|
||||
|
||||
db, err := sql.Open("postgres", connStr)
|
||||
if err != nil {
|
||||
return nil, func() {}, fmt.Errorf("error connecting to database: %w", err)
|
||||
|
@ -475,8 +475,6 @@ func (r *repositorySQL) Participants(
|
||||
})
|
||||
}
|
||||
|
||||
fmt.Println(query.ToSql())
|
||||
|
||||
rows, err := query.RunWith(r.Conn(ctx)).QueryContext(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error fetch employees from database. %w", err)
|
||||
@ -740,8 +738,6 @@ func (r *repositorySQL) fetchEmployees(
|
||||
})
|
||||
}
|
||||
|
||||
fmt.Println(query.ToSql())
|
||||
|
||||
rows, err := query.RunWith(r.Conn(ctx)).QueryContext(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error fetch employees from database. %w", err)
|
||||
@ -808,7 +804,7 @@ func (r *repositorySQL) AddEmployee(ctx context.Context, employee models.Employe
|
||||
employee.WalletAddress,
|
||||
employee.CreatedAt,
|
||||
employee.UpdatedAt,
|
||||
)
|
||||
).PlaceholderFormat(sq.Dollar)
|
||||
|
||||
if _, err := query.RunWith(r.Conn(ctx)).ExecContext(ctx); err != nil {
|
||||
return fmt.Errorf("error add employee. %w", err)
|
||||
|
@ -50,6 +50,8 @@ type Repository interface {
|
||||
|
||||
ConfirmTransaction(ctx context.Context, params ConfirmTransactionParams) error
|
||||
CancelTransaction(ctx context.Context, params CancelTransactionParams) error
|
||||
|
||||
AddMultisig(ctx context.Context, multisig models.Multisig) error
|
||||
}
|
||||
|
||||
type repositorySQL struct {
|
||||
@ -89,8 +91,6 @@ func (r *repositorySQL) GetTransactions(
|
||||
}
|
||||
}()
|
||||
|
||||
fmt.Println(query.ToSql())
|
||||
|
||||
for rows.Next() {
|
||||
var (
|
||||
id uuid.UUID
|
||||
@ -400,3 +400,48 @@ func buildGetTransactionsQuery(params GetTransactionsParams) sq.SelectBuilder {
|
||||
|
||||
return query
|
||||
}
|
||||
|
||||
func (r *repositorySQL) AddMultisig(
|
||||
ctx context.Context,
|
||||
multisig models.Multisig,
|
||||
) error {
|
||||
return sqltools.Transaction(ctx, r.db, func(ctx context.Context) error {
|
||||
query := sq.Insert("multisigs").Columns(
|
||||
"id",
|
||||
"organization_id",
|
||||
"title",
|
||||
"created_at",
|
||||
"updated_at",
|
||||
).Values(
|
||||
multisig.ID,
|
||||
multisig.OrganizationID,
|
||||
multisig.Title,
|
||||
multisig.CreatedAt,
|
||||
multisig.UpdatedAt,
|
||||
).PlaceholderFormat(sq.Dollar)
|
||||
|
||||
if _, err := query.RunWith(r.Conn(ctx)).ExecContext(ctx); err != nil {
|
||||
return fmt.Errorf("error insert multisig data. %w", err)
|
||||
}
|
||||
|
||||
for _, owner := range multisig.Owners {
|
||||
addOwnerQuery := sq.Insert("multisig_owners").Columns(
|
||||
"multisig_id",
|
||||
"owner_id",
|
||||
"created_at",
|
||||
"updated_at",
|
||||
).Values(
|
||||
multisig.ID,
|
||||
owner.Id(),
|
||||
multisig.CreatedAt,
|
||||
multisig.UpdatedAt,
|
||||
)
|
||||
|
||||
if _, err := addOwnerQuery.RunWith(r.Conn(ctx)).ExecContext(ctx); err != nil {
|
||||
return fmt.Errorf("error insert multisig owner data. %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
@ -72,8 +72,6 @@ func (r *repositorySQL) Get(ctx context.Context, params GetParams) ([]*models.Us
|
||||
query = query.Where("u.seed = ?", params.Seed)
|
||||
}
|
||||
|
||||
fmt.Println(query.ToSql())
|
||||
|
||||
rows, err := query.RunWith(r.Conn(ctx)).QueryContext(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error fetch data from database. %w", err)
|
||||
|
@ -149,16 +149,18 @@ create table contracts (
|
||||
updated_at timestamp default current_timestamp
|
||||
);
|
||||
|
||||
create intex if not exists idx_contracts_organization_id_multisig
|
||||
create index if not exists idx_contracts_organization_id_multisig
|
||||
on contracts (organization_id, multisig);
|
||||
|
||||
create intex if not exists idx_contracts_organization_id_created_by
|
||||
create index if not exists idx_contracts_organization_id_created_by
|
||||
on contracts (organization_id, created_by);
|
||||
|
||||
create table multisigs (
|
||||
id uuid primary key,
|
||||
organization_id uuid not null references organizations(id),
|
||||
title varchar(350) default 'New Multi-Sig'
|
||||
title varchar(350) default 'New Multi-Sig',
|
||||
created_at timestamp default current_timestamp,
|
||||
updated_at timestamp default current_timestamp
|
||||
);
|
||||
|
||||
create table multisig_owners (
|
||||
@ -169,10 +171,10 @@ create table multisig_owners (
|
||||
primary key (multisig_id, owner_id)
|
||||
);
|
||||
|
||||
create intex if not exists idx_multisig_owners_multisig_id
|
||||
create index if not exists idx_multisig_owners_multisig_id
|
||||
on multisig_owners (multisig_id);
|
||||
|
||||
create intex if not exists idx_multisig_owners_owner_id
|
||||
create index if not exists idx_multisig_owners_owner_id
|
||||
on multisig_owners (owner_id);
|
||||
|
||||
create table multisig_confirmations (
|
||||
@ -182,14 +184,14 @@ create table multisig_confirmations (
|
||||
primary key (multisig_id, owner_id)
|
||||
);
|
||||
|
||||
create intex if not exists idx_multisig_confirmations_owners_multisig_id
|
||||
create index if not exists idx_multisig_confirmations_owners_multisig_id
|
||||
on multisig_confirmations (multisig_id);
|
||||
|
||||
create intex if not exists idx_multisig_confirmations_owners_owner_id
|
||||
create index if not exists idx_multisig_confirmations_owners_owner_id
|
||||
on multisig_confirmations (owner_id);
|
||||
|
||||
create table invites (
|
||||
link_hash bytea primary key,
|
||||
link_hash varchar(64) primary key,
|
||||
created_by uuid not null references users(id),
|
||||
created_at timestamp default current_timestamp,
|
||||
expired_at timestamp default null,
|
||||
|
554
backend/test.txt
554
backend/test.txt
@ -1,554 +0,0 @@
|
||||
<Valuta name="Foreign Currency Market Lib">
|
||||
<Item ID="R01010">
|
||||
<Name>Австралийский доллар</Name>
|
||||
<EngName>Australian Dollar</EngName>
|
||||
<Nominal>1</Nominal>
|
||||
<ParentCode>R01010 </ParentCode>
|
||||
<ISO_Num_Code>36</ISO_Num_Code>
|
||||
<ISO_Char_Code>AUD</ISO_Char_Code>
|
||||
</Item>
|
||||
<Item ID="R01015">
|
||||
<Name>Австрийский шиллинг</Name>
|
||||
<EngName>Austrian Shilling</EngName>
|
||||
<Nominal>1000</Nominal>
|
||||
<ParentCode>R01015 </ParentCode>
|
||||
<ISO_Num_Code>40</ISO_Num_Code>
|
||||
<ISO_Char_Code>ATS</ISO_Char_Code>
|
||||
</Item>
|
||||
<Item ID="R01020A">
|
||||
<Name>Азербайджанский манат</Name>
|
||||
<EngName>Azerbaijan Manat</EngName>
|
||||
<Nominal>1</Nominal>
|
||||
<ParentCode>R01020 </ParentCode>
|
||||
<ISO_Num_Code>944</ISO_Num_Code>
|
||||
<ISO_Char_Code>AZN</ISO_Char_Code>
|
||||
</Item>
|
||||
<Item ID="R01035">
|
||||
<Name>Фунт стерлингов Соединенного королевства</Name>
|
||||
<EngName>British Pound Sterling</EngName>
|
||||
<Nominal>1</Nominal>
|
||||
<ParentCode>R01035 </ParentCode>
|
||||
<ISO_Num_Code>826</ISO_Num_Code>
|
||||
<ISO_Char_Code>GBP</ISO_Char_Code>
|
||||
</Item>
|
||||
<Item ID="R01040F">
|
||||
<Name>Ангольская новая кванза</Name>
|
||||
<EngName>Angolan new Kwanza</EngName>
|
||||
<Nominal>100000</Nominal>
|
||||
<ParentCode>R01040 </ParentCode>
|
||||
<ISO_Num_Code>24</ISO_Num_Code>
|
||||
<ISO_Char_Code>AON</ISO_Char_Code>
|
||||
</Item>
|
||||
<Item ID="R01060">
|
||||
<Name>Армянский драм</Name>
|
||||
<EngName>Armenia Dram</EngName>
|
||||
<Nominal>100</Nominal>
|
||||
<ParentCode>R01060 </ParentCode>
|
||||
<ISO_Num_Code>51</ISO_Num_Code>
|
||||
<ISO_Char_Code>AMD</ISO_Char_Code>
|
||||
</Item>
|
||||
<Item ID="R01090B">
|
||||
<Name>Белорусский рубль</Name>
|
||||
<EngName>Belarussian Ruble</EngName>
|
||||
<Nominal>1</Nominal>
|
||||
<ParentCode>R01090 </ParentCode>
|
||||
<ISO_Num_Code>933</ISO_Num_Code>
|
||||
<ISO_Char_Code>BYN</ISO_Char_Code>
|
||||
</Item>
|
||||
<Item ID="R01095">
|
||||
<Name>Бельгийский франк</Name>
|
||||
<EngName>Belgium Franc</EngName>
|
||||
<Nominal>1000</Nominal>
|
||||
<ParentCode>R01095 </ParentCode>
|
||||
<ISO_Num_Code>56</ISO_Num_Code>
|
||||
<ISO_Char_Code>BEF</ISO_Char_Code>
|
||||
</Item>
|
||||
<Item ID="R01100">
|
||||
<Name>Болгарский лев</Name>
|
||||
<EngName>Bulgarian lev</EngName>
|
||||
<Nominal>1</Nominal>
|
||||
<ParentCode>R01100 </ParentCode>
|
||||
<ISO_Num_Code>975</ISO_Num_Code>
|
||||
<ISO_Char_Code>BGN</ISO_Char_Code>
|
||||
</Item>
|
||||
<Item ID="R01115">
|
||||
<Name>Бразильский реал</Name>
|
||||
<EngName>Brazil Real</EngName>
|
||||
<Nominal>1</Nominal>
|
||||
<ParentCode>R01115 </ParentCode>
|
||||
<ISO_Num_Code>986</ISO_Num_Code>
|
||||
<ISO_Char_Code>BRL</ISO_Char_Code>
|
||||
</Item>
|
||||
<Item ID="R01135">
|
||||
<Name>Венгерский форинт</Name>
|
||||
<EngName>Hungarian Forint</EngName>
|
||||
<Nominal>100</Nominal>
|
||||
<ParentCode>R01135 </ParentCode>
|
||||
<ISO_Num_Code>348</ISO_Num_Code>
|
||||
<ISO_Char_Code>HUF</ISO_Char_Code>
|
||||
</Item>
|
||||
<Item ID="R01150">
|
||||
<Name>Вьетнамский донг</Name>
|
||||
<EngName>Vietnam Dong</EngName>
|
||||
<Nominal>10000</Nominal>
|
||||
<ParentCode>R01150 </ParentCode>
|
||||
<ISO_Num_Code>704</ISO_Num_Code>
|
||||
<ISO_Char_Code>VND</ISO_Char_Code>
|
||||
</Item>
|
||||
<Item ID="R01200">
|
||||
<Name>Гонконгский доллар</Name>
|
||||
<EngName>Hong Kong Dollar</EngName>
|
||||
<Nominal>1</Nominal>
|
||||
<ParentCode>R01200 </ParentCode>
|
||||
<ISO_Num_Code>344</ISO_Num_Code>
|
||||
<ISO_Char_Code>HKD</ISO_Char_Code>
|
||||
</Item>
|
||||
<Item ID="R01205">
|
||||
<Name>Греческая драхма</Name>
|
||||
<EngName>Greek Drachma</EngName>
|
||||
<Nominal>10000</Nominal>
|
||||
<ParentCode>R01205 </ParentCode>
|
||||
<ISO_Num_Code>300</ISO_Num_Code>
|
||||
<ISO_Char_Code>GRD</ISO_Char_Code>
|
||||
</Item>
|
||||
<Item ID="R01210">
|
||||
<Name>Грузинский лари</Name>
|
||||
<EngName>Georgia Lari</EngName>
|
||||
<Nominal>1</Nominal>
|
||||
<ParentCode>R01210 </ParentCode>
|
||||
<ISO_Num_Code>981</ISO_Num_Code>
|
||||
<ISO_Char_Code>GEL</ISO_Char_Code>
|
||||
</Item>
|
||||
<Item ID="R01215">
|
||||
<Name>Датская крона</Name>
|
||||
<EngName>Danish Krone</EngName>
|
||||
<Nominal>1</Nominal>
|
||||
<ParentCode>R01215 </ParentCode>
|
||||
<ISO_Num_Code>208</ISO_Num_Code>
|
||||
<ISO_Char_Code>DKK</ISO_Char_Code>
|
||||
</Item>
|
||||
<Item ID="R01230">
|
||||
<Name>Дирхам ОАЭ</Name>
|
||||
<EngName>UAE Dirham</EngName>
|
||||
<Nominal>1</Nominal>
|
||||
<ParentCode>R01230 </ParentCode>
|
||||
<ISO_Num_Code>784</ISO_Num_Code>
|
||||
<ISO_Char_Code>AED</ISO_Char_Code>
|
||||
</Item>
|
||||
<Item ID="R01235">
|
||||
<Name>Доллар США</Name>
|
||||
<EngName>US Dollar</EngName>
|
||||
<Nominal>1</Nominal>
|
||||
<ParentCode>R01235 </ParentCode>
|
||||
<ISO_Num_Code>840</ISO_Num_Code>
|
||||
<ISO_Char_Code>USD</ISO_Char_Code>
|
||||
</Item>
|
||||
<Item ID="R01239">
|
||||
<Name>Евро</Name>
|
||||
<EngName>Euro</EngName>
|
||||
<Nominal>1</Nominal>
|
||||
<ParentCode>R01239 </ParentCode>
|
||||
<ISO_Num_Code>978</ISO_Num_Code>
|
||||
<ISO_Char_Code>EUR</ISO_Char_Code>
|
||||
</Item>
|
||||
<Item ID="R01240">
|
||||
<Name>Египетский фунт</Name>
|
||||
<EngName>Egyptian Pound</EngName>
|
||||
<Nominal>10</Nominal>
|
||||
<ParentCode>R01240 </ParentCode>
|
||||
<ISO_Num_Code>818</ISO_Num_Code>
|
||||
<ISO_Char_Code>EGP</ISO_Char_Code>
|
||||
</Item>
|
||||
<Item ID="R01270">
|
||||
<Name>Индийская рупия</Name>
|
||||
<EngName>Indian Rupee</EngName>
|
||||
<Nominal>10</Nominal>
|
||||
<ParentCode>R01270 </ParentCode>
|
||||
<ISO_Num_Code>356</ISO_Num_Code>
|
||||
<ISO_Char_Code>INR</ISO_Char_Code>
|
||||
</Item>
|
||||
<Item ID="R01280">
|
||||
<Name>Индонезийская рупия</Name>
|
||||
<EngName>Indonesian Rupiah</EngName>
|
||||
<Nominal>10000</Nominal>
|
||||
<ParentCode>R01280 </ParentCode>
|
||||
<ISO_Num_Code>360</ISO_Num_Code>
|
||||
<ISO_Char_Code>IDR</ISO_Char_Code>
|
||||
</Item>
|
||||
<Item ID="R01305">
|
||||
<Name>Ирландский фунт</Name>
|
||||
<EngName>Irish Pound</EngName>
|
||||
<Nominal>100</Nominal>
|
||||
<ParentCode>R01305 </ParentCode>
|
||||
<ISO_Num_Code>372</ISO_Num_Code>
|
||||
<ISO_Char_Code>IEP</ISO_Char_Code>
|
||||
</Item>
|
||||
<Item ID="R01310">
|
||||
<Name>Исландская крона</Name>
|
||||
<EngName>Iceland Krona</EngName>
|
||||
<Nominal>10000</Nominal>
|
||||
<ParentCode>R01310 </ParentCode>
|
||||
<ISO_Num_Code>352</ISO_Num_Code>
|
||||
<ISO_Char_Code>ISK</ISO_Char_Code>
|
||||
</Item>
|
||||
<Item ID="R01315">
|
||||
<Name>Испанская песета</Name>
|
||||
<EngName>Spanish Peseta</EngName>
|
||||
<Nominal>10000</Nominal>
|
||||
<ParentCode>R01315 </ParentCode>
|
||||
<ISO_Num_Code>724</ISO_Num_Code>
|
||||
<ISO_Char_Code>ESP</ISO_Char_Code>
|
||||
</Item>
|
||||
<Item ID="R01325">
|
||||
<Name>Итальянская лира</Name>
|
||||
<EngName>Italian Lira</EngName>
|
||||
<Nominal>100000</Nominal>
|
||||
<ParentCode>R01325 </ParentCode>
|
||||
<ISO_Num_Code>380</ISO_Num_Code>
|
||||
<ISO_Char_Code>ITL</ISO_Char_Code>
|
||||
</Item>
|
||||
<Item ID="R01335">
|
||||
<Name>Казахстанский тенге</Name>
|
||||
<EngName>Kazakhstan Tenge</EngName>
|
||||
<Nominal>100</Nominal>
|
||||
<ParentCode>R01335 </ParentCode>
|
||||
<ISO_Num_Code>398</ISO_Num_Code>
|
||||
<ISO_Char_Code>KZT</ISO_Char_Code>
|
||||
</Item>
|
||||
<Item ID="R01350">
|
||||
<Name>Канадский доллар</Name>
|
||||
<EngName>Canadian Dollar</EngName>
|
||||
<Nominal>1</Nominal>
|
||||
<ParentCode>R01350 </ParentCode>
|
||||
<ISO_Num_Code>124</ISO_Num_Code>
|
||||
<ISO_Char_Code>CAD</ISO_Char_Code>
|
||||
</Item>
|
||||
<Item ID="R01355">
|
||||
<Name>Катарский риал</Name>
|
||||
<EngName>Qatari Riyal</EngName>
|
||||
<Nominal>1</Nominal>
|
||||
<ParentCode>R01355 </ParentCode>
|
||||
<ISO_Num_Code>634</ISO_Num_Code>
|
||||
<ISO_Char_Code>QAR</ISO_Char_Code>
|
||||
</Item>
|
||||
<Item ID="R01370">
|
||||
<Name>Киргизский сом</Name>
|
||||
<EngName>Kyrgyzstan Som</EngName>
|
||||
<Nominal>10</Nominal>
|
||||
<ParentCode>R01370 </ParentCode>
|
||||
<ISO_Num_Code>417</ISO_Num_Code>
|
||||
<ISO_Char_Code>KGS</ISO_Char_Code>
|
||||
</Item>
|
||||
<Item ID="R01375">
|
||||
<Name>Китайский юань</Name>
|
||||
<EngName>China Yuan</EngName>
|
||||
<Nominal>1</Nominal>
|
||||
<ParentCode>R01375 </ParentCode>
|
||||
<ISO_Num_Code>156</ISO_Num_Code>
|
||||
<ISO_Char_Code>CNY</ISO_Char_Code>
|
||||
</Item>
|
||||
<Item ID="R01390">
|
||||
<Name>Кувейтский динар</Name>
|
||||
<EngName>Kuwaiti Dinar</EngName>
|
||||
<Nominal>10</Nominal>
|
||||
<ParentCode>R01390 </ParentCode>
|
||||
<ISO_Num_Code>414</ISO_Num_Code>
|
||||
<ISO_Char_Code>KWD</ISO_Char_Code>
|
||||
</Item>
|
||||
<Item ID="R01405">
|
||||
<Name>Латвийский лат</Name>
|
||||
<EngName>Latvian Lat</EngName>
|
||||
<Nominal>1</Nominal>
|
||||
<ParentCode>R01405 </ParentCode>
|
||||
<ISO_Num_Code>428</ISO_Num_Code>
|
||||
<ISO_Char_Code>LVL</ISO_Char_Code>
|
||||
</Item>
|
||||
<Item ID="R01420">
|
||||
<Name>Ливанский фунт</Name>
|
||||
<EngName>Lebanese Pound</EngName>
|
||||
<Nominal>100000</Nominal>
|
||||
<ParentCode>R01420 </ParentCode>
|
||||
<ISO_Num_Code>422</ISO_Num_Code>
|
||||
<ISO_Char_Code>LBP</ISO_Char_Code>
|
||||
</Item>
|
||||
<Item ID="R01435">
|
||||
<Name>Литовский лит</Name>
|
||||
<EngName>Lithuanian Lita</EngName>
|
||||
<Nominal>1</Nominal>
|
||||
<ParentCode>R01435 </ParentCode>
|
||||
<ISO_Num_Code>440</ISO_Num_Code>
|
||||
<ISO_Char_Code>LTL</ISO_Char_Code>
|
||||
</Item>
|
||||
<Item ID="R01436">
|
||||
<Name>Литовский талон</Name>
|
||||
<EngName>Lithuanian talon</EngName>
|
||||
<Nominal>1</Nominal>
|
||||
<ParentCode>R01435 </ParentCode>
|
||||
<ISO_Num_Code/>
|
||||
<ISO_Char_Code/>
|
||||
</Item>
|
||||
<Item ID="R01500">
|
||||
<Name>Молдавский лей</Name>
|
||||
<EngName>Moldova Lei</EngName>
|
||||
<Nominal>10</Nominal>
|
||||
<ParentCode>R01500 </ParentCode>
|
||||
<ISO_Num_Code>498</ISO_Num_Code>
|
||||
<ISO_Char_Code>MDL</ISO_Char_Code>
|
||||
</Item>
|
||||
<Item ID="R01510">
|
||||
<Name>Немецкая марка</Name>
|
||||
<EngName>Deutsche Mark</EngName>
|
||||
<Nominal>1</Nominal>
|
||||
<ParentCode>R01510 </ParentCode>
|
||||
<ISO_Num_Code>276</ISO_Num_Code>
|
||||
<ISO_Char_Code>DEM</ISO_Char_Code>
|
||||
</Item>
|
||||
<Item ID="R01510A">
|
||||
<Name>Немецкая марка</Name>
|
||||
<EngName>Deutsche Mark</EngName>
|
||||
<Nominal>100</Nominal>
|
||||
<ParentCode>R01510 </ParentCode>
|
||||
<ISO_Num_Code>280</ISO_Num_Code>
|
||||
<ISO_Char_Code>DEM</ISO_Char_Code>
|
||||
</Item>
|
||||
<Item ID="R01523">
|
||||
<Name>Нидерландский гульден</Name>
|
||||
<EngName>Netherlands Gulden</EngName>
|
||||
<Nominal>100</Nominal>
|
||||
<ParentCode>R01523 </ParentCode>
|
||||
<ISO_Num_Code>528</ISO_Num_Code>
|
||||
<ISO_Char_Code>NLG</ISO_Char_Code>
|
||||
</Item>
|
||||
<Item ID="R01530">
|
||||
<Name>Новозеландский доллар</Name>
|
||||
<EngName>New Zealand Dollar</EngName>
|
||||
<Nominal>1</Nominal>
|
||||
<ParentCode>R01530 </ParentCode>
|
||||
<ISO_Num_Code>554</ISO_Num_Code>
|
||||
<ISO_Char_Code>NZD</ISO_Char_Code>
|
||||
</Item>
|
||||
<Item ID="R01535">
|
||||
<Name>Норвежская крона</Name>
|
||||
<EngName>Norwegian Krone</EngName>
|
||||
<Nominal>10</Nominal>
|
||||
<ParentCode>R01535 </ParentCode>
|
||||
<ISO_Num_Code>578</ISO_Num_Code>
|
||||
<ISO_Char_Code>NOK</ISO_Char_Code>
|
||||
</Item>
|
||||
<Item ID="R01565">
|
||||
<Name>Польский злотый</Name>
|
||||
<EngName>Polish Zloty</EngName>
|
||||
<Nominal>1</Nominal>
|
||||
<ParentCode>R01565 </ParentCode>
|
||||
<ISO_Num_Code>985</ISO_Num_Code>
|
||||
<ISO_Char_Code>PLN</ISO_Char_Code>
|
||||
</Item>
|
||||
<Item ID="R01570">
|
||||
<Name>Португальский эскудо</Name>
|
||||
<EngName>Portuguese Escudo</EngName>
|
||||
<Nominal>10000</Nominal>
|
||||
<ParentCode>R01570 </ParentCode>
|
||||
<ISO_Num_Code>620</ISO_Num_Code>
|
||||
<ISO_Char_Code>PTE</ISO_Char_Code>
|
||||
</Item>
|
||||
<Item ID="R01585">
|
||||
<Name>Румынский лей</Name>
|
||||
<EngName>Romanian Leu</EngName>
|
||||
<Nominal>10000</Nominal>
|
||||
<ParentCode>R01585 </ParentCode>
|
||||
<ISO_Num_Code>642</ISO_Num_Code>
|
||||
<ISO_Char_Code>ROL</ISO_Char_Code>
|
||||
</Item>
|
||||
<Item ID="R01585F">
|
||||
<Name>Румынский лей</Name>
|
||||
<EngName>Romanian Leu</EngName>
|
||||
<Nominal>1</Nominal>
|
||||
<ParentCode>R01585 </ParentCode>
|
||||
<ISO_Num_Code>946</ISO_Num_Code>
|
||||
<ISO_Char_Code>RON</ISO_Char_Code>
|
||||
</Item>
|
||||
<Item ID="R01589">
|
||||
<Name>СДР (специальные права заимствования)</Name>
|
||||
<EngName>SDR</EngName>
|
||||
<Nominal>1</Nominal>
|
||||
<ParentCode>R01589 </ParentCode>
|
||||
<ISO_Num_Code>960</ISO_Num_Code>
|
||||
<ISO_Char_Code>XDR</ISO_Char_Code>
|
||||
</Item>
|
||||
<Item ID="R01625">
|
||||
<Name>Сингапурский доллар</Name>
|
||||
<EngName>Singapore Dollar</EngName>
|
||||
<Nominal>1</Nominal>
|
||||
<ParentCode>R01625 </ParentCode>
|
||||
<ISO_Num_Code>702</ISO_Num_Code>
|
||||
<ISO_Char_Code>SGD</ISO_Char_Code>
|
||||
</Item>
|
||||
<Item ID="R01665A">
|
||||
<Name>Суринамский доллар</Name>
|
||||
<EngName>Surinam Dollar</EngName>
|
||||
<Nominal>1</Nominal>
|
||||
<ParentCode>R01665 </ParentCode>
|
||||
<ISO_Num_Code>968</ISO_Num_Code>
|
||||
<ISO_Char_Code>SRD</ISO_Char_Code>
|
||||
</Item>
|
||||
<Item ID="R01670">
|
||||
<Name>Таджикский сомони</Name>
|
||||
<EngName>Tajikistan Ruble</EngName>
|
||||
<Nominal>10</Nominal>
|
||||
<ParentCode>R01670 </ParentCode>
|
||||
<ISO_Num_Code>972</ISO_Num_Code>
|
||||
<ISO_Char_Code>TJS</ISO_Char_Code>
|
||||
</Item>
|
||||
<Item ID="R01675">
|
||||
<Name>Таиландский бат</Name>
|
||||
<EngName>Thai Baht</EngName>
|
||||
<Nominal>10</Nominal>
|
||||
<ParentCode>R01675 </ParentCode>
|
||||
<ISO_Num_Code>764</ISO_Num_Code>
|
||||
<ISO_Char_Code>THB</ISO_Char_Code>
|
||||
</Item>
|
||||
<Item ID="R01700J">
|
||||
<Name>Турецкая лира</Name>
|
||||
<EngName>Turkish Lira</EngName>
|
||||
<Nominal>10</Nominal>
|
||||
<ParentCode>R01700 </ParentCode>
|
||||
<ISO_Num_Code>949</ISO_Num_Code>
|
||||
<ISO_Char_Code>TRY</ISO_Char_Code>
|
||||
</Item>
|
||||
<Item ID="R01710">
|
||||
<Name>Туркменский манат</Name>
|
||||
<EngName>Turkmenistan Manat</EngName>
|
||||
<Nominal>10000</Nominal>
|
||||
<ParentCode>R01710 </ParentCode>
|
||||
<ISO_Num_Code>795</ISO_Num_Code>
|
||||
<ISO_Char_Code>TMM</ISO_Char_Code>
|
||||
</Item>
|
||||
<Item ID="R01710A">
|
||||
<Name>Новый туркменский манат</Name>
|
||||
<EngName>New Turkmenistan Manat</EngName>
|
||||
<Nominal>1</Nominal>
|
||||
<ParentCode>R01710 </ParentCode>
|
||||
<ISO_Num_Code>934</ISO_Num_Code>
|
||||
<ISO_Char_Code>TMT</ISO_Char_Code>
|
||||
</Item>
|
||||
<Item ID="R01717">
|
||||
<Name>Узбекский сум</Name>
|
||||
<EngName>Uzbekistan Sum</EngName>
|
||||
<Nominal>10000</Nominal>
|
||||
<ParentCode>R01717 </ParentCode>
|
||||
<ISO_Num_Code>860</ISO_Num_Code>
|
||||
<ISO_Char_Code>UZS</ISO_Char_Code>
|
||||
</Item>
|
||||
<Item ID="R01720">
|
||||
<Name>Украинская гривна</Name>
|
||||
<EngName>Ukrainian Hryvnia</EngName>
|
||||
<Nominal>10</Nominal>
|
||||
<ParentCode>R01720 </ParentCode>
|
||||
<ISO_Num_Code>980</ISO_Num_Code>
|
||||
<ISO_Char_Code>UAH</ISO_Char_Code>
|
||||
</Item>
|
||||
<Item ID="R01720A">
|
||||
<Name>Украинский карбованец</Name>
|
||||
<EngName>Ukrainian Hryvnia</EngName>
|
||||
<Nominal>1</Nominal>
|
||||
<ParentCode>R01720 </ParentCode>
|
||||
<ISO_Num_Code/>
|
||||
<ISO_Char_Code/>
|
||||
</Item>
|
||||
<Item ID="R01740">
|
||||
<Name>Финляндская марка</Name>
|
||||
<EngName>Finnish Marka</EngName>
|
||||
<Nominal>100</Nominal>
|
||||
<ParentCode>R01740 </ParentCode>
|
||||
<ISO_Num_Code>246</ISO_Num_Code>
|
||||
<ISO_Char_Code>FIM</ISO_Char_Code>
|
||||
</Item>
|
||||
<Item ID="R01750">
|
||||
<Name>Французский франк</Name>
|
||||
<EngName>French Franc</EngName>
|
||||
<Nominal>1000</Nominal>
|
||||
<ParentCode>R01750 </ParentCode>
|
||||
<ISO_Num_Code>250</ISO_Num_Code>
|
||||
<ISO_Char_Code>FRF</ISO_Char_Code>
|
||||
</Item>
|
||||
<Item ID="R01760">
|
||||
<Name>Чешская крона</Name>
|
||||
<EngName>Czech Koruna</EngName>
|
||||
<Nominal>10</Nominal>
|
||||
<ParentCode>R01760 </ParentCode>
|
||||
<ISO_Num_Code>203</ISO_Num_Code>
|
||||
<ISO_Char_Code>CZK</ISO_Char_Code>
|
||||
</Item>
|
||||
<Item ID="R01770">
|
||||
<Name>Шведская крона</Name>
|
||||
<EngName>Swedish Krona</EngName>
|
||||
<Nominal>10</Nominal>
|
||||
<ParentCode>R01770 </ParentCode>
|
||||
<ISO_Num_Code>752</ISO_Num_Code>
|
||||
<ISO_Char_Code>SEK</ISO_Char_Code>
|
||||
</Item>
|
||||
<Item ID="R01775">
|
||||
<Name>Швейцарский франк</Name>
|
||||
<EngName>Swiss Franc</EngName>
|
||||
<Nominal>1</Nominal>
|
||||
<ParentCode>R01775 </ParentCode>
|
||||
<ISO_Num_Code>756</ISO_Num_Code>
|
||||
<ISO_Char_Code>CHF</ISO_Char_Code>
|
||||
</Item>
|
||||
<Item ID="R01790">
|
||||
<Name>ЭКЮ</Name>
|
||||
<EngName>ECU</EngName>
|
||||
<Nominal>1</Nominal>
|
||||
<ParentCode>R01790 </ParentCode>
|
||||
<ISO_Num_Code>954</ISO_Num_Code>
|
||||
<ISO_Char_Code>XEU</ISO_Char_Code>
|
||||
</Item>
|
||||
<Item ID="R01795">
|
||||
<Name>Эстонская крона</Name>
|
||||
<EngName>Estonian Kroon</EngName>
|
||||
<Nominal>10</Nominal>
|
||||
<ParentCode>R01795 </ParentCode>
|
||||
<ISO_Num_Code>233</ISO_Num_Code>
|
||||
<ISO_Char_Code>EEK</ISO_Char_Code>
|
||||
</Item>
|
||||
<Item ID="R01805">
|
||||
<Name>Югославский новый динар</Name>
|
||||
<EngName>Yugoslavian Dinar</EngName>
|
||||
<Nominal>1</Nominal>
|
||||
<ParentCode>R01804 </ParentCode>
|
||||
<ISO_Num_Code>890</ISO_Num_Code>
|
||||
<ISO_Char_Code>YUN</ISO_Char_Code>
|
||||
</Item>
|
||||
<Item ID="R01805F">
|
||||
<Name>Сербский динар</Name>
|
||||
<EngName>Serbian Dinar</EngName>
|
||||
<Nominal>100</Nominal>
|
||||
<ParentCode>R01804 </ParentCode>
|
||||
<ISO_Num_Code>941</ISO_Num_Code>
|
||||
<ISO_Char_Code>RSD</ISO_Char_Code>
|
||||
</Item>
|
||||
<Item ID="R01810">
|
||||
<Name>Южноафриканский рэнд</Name>
|
||||
<EngName>S.African Rand</EngName>
|
||||
<Nominal>10</Nominal>
|
||||
<ParentCode>R01810 </ParentCode>
|
||||
<ISO_Num_Code>710</ISO_Num_Code>
|
||||
<ISO_Char_Code>ZAR</ISO_Char_Code>
|
||||
</Item>
|
||||
<Item ID="R01815">
|
||||
<Name>Вон Республики Корея</Name>
|
||||
<EngName>South Korean Won</EngName>
|
||||
<Nominal>1000</Nominal>
|
||||
<ParentCode>R01815 </ParentCode>
|
||||
<ISO_Num_Code>410</ISO_Num_Code>
|
||||
<ISO_Char_Code>KRW</ISO_Char_Code>
|
||||
</Item>
|
||||
<Item ID="R01820">
|
||||
<Name>Японская иена</Name>
|
||||
<EngName>Japanese Yen</EngName>
|
||||
<Nominal>100</Nominal>
|
||||
<ParentCode>R01820 </ParentCode>
|
||||
<ISO_Num_Code>392</ISO_Num_Code>
|
||||
<ISO_Char_Code>JPY</ISO_Char_Code>
|
||||
</Item>
|
||||
</Valuta>
|
Loading…
Reference in New Issue
Block a user