1{ config, lib, pkgs, ... }:
2
3with lib;
4
5let
6 cfg = config.services.rippleDataApi;
7
8 deployment_env_config = builtins.toJSON {
9 production = {
10 port = toString cfg.port;
11 maxSockets = 150;
12 batchSize = 100;
13 startIndex = 32570;
14 rippleds = cfg.rippleds;
15 redis = {
16 enable = cfg.redis.enable;
17 host = cfg.redis.host;
18 port = cfg.redis.port;
19 options.auth_pass = null;
20 };
21 };
22 };
23
24 db_config = builtins.toJSON {
25 production = {
26 username = optional (cfg.couchdb.pass != "") cfg.couchdb.user;
27 password = optional (cfg.couchdb.pass != "") cfg.couchdb.pass;
28 host = cfg.couchdb.host;
29 port = cfg.couchdb.port;
30 database = cfg.couchdb.db;
31 protocol = "http";
32 };
33 };
34
35in {
36 options = {
37 services.rippleDataApi = {
38 enable = mkEnableOption "ripple data api";
39
40 port = mkOption {
41 description = "Ripple data api port";
42 default = 5993;
43 type = types.int;
44 };
45
46 importMode = mkOption {
47 description = "Ripple data api import mode.";
48 default = "liveOnly";
49 type = types.enum ["live" "liveOnly"];
50 };
51
52 minLedger = mkOption {
53 description = "Ripple data api minimal ledger to fetch.";
54 default = null;
55 type = types.nullOr types.int;
56 };
57
58 maxLedger = mkOption {
59 description = "Ripple data api maximal ledger to fetch.";
60 default = null;
61 type = types.nullOr types.int;
62 };
63
64 redis = {
65 enable = mkOption {
66 description = "Whether to enable caching of ripple data to redis.";
67 default = true;
68 type = types.bool;
69 };
70
71 host = mkOption {
72 description = "Ripple data api redis host.";
73 default = "localhost";
74 type = types.str;
75 };
76
77 port = mkOption {
78 description = "Ripple data api redis port.";
79 default = 5984;
80 type = types.int;
81 };
82 };
83
84 couchdb = {
85 host = mkOption {
86 description = "Ripple data api couchdb host.";
87 default = "localhost";
88 type = types.str;
89 };
90
91 port = mkOption {
92 description = "Ripple data api couchdb port.";
93 default = 5984;
94 type = types.int;
95 };
96
97 db = mkOption {
98 description = "Ripple data api couchdb database.";
99 default = "rippled";
100 type = types.str;
101 };
102
103 user = mkOption {
104 description = "Ripple data api couchdb username.";
105 default = "rippled";
106 type = types.str;
107 };
108
109 pass = mkOption {
110 description = "Ripple data api couchdb password.";
111 default = "";
112 type = types.str;
113 };
114
115 create = mkOption {
116 description = "Whether to create couchdb database needed by ripple data api.";
117 type = types.bool;
118 default = true;
119 };
120 };
121
122 rippleds = mkOption {
123 description = "List of rippleds to be used by ripple data api.";
124 default = [
125 "http://s_east.ripple.com:51234"
126 "http://s_west.ripple.com:51234"
127 ];
128 type = types.listOf types.str;
129 };
130 };
131 };
132
133 config = mkIf (cfg.enable) {
134 services.couchdb.enable = mkDefault true;
135 services.couchdb.bindAddress = mkDefault "0.0.0.0";
136 services.redis.enable = mkDefault true;
137
138 systemd.services.ripple-data-api = {
139 after = [ "couchdb.service" "redis.service" "ripple-data-api-importer.service" ];
140 wantedBy = [ "multi-user.target" ];
141
142 environment = {
143 NODE_ENV = "production";
144 DEPLOYMENT_ENVS_CONFIG = pkgs.writeText "deployment.environment.json" deployment_env_config;
145 DB_CONFIG = pkgs.writeText "db.config.json" db_config;
146 };
147
148 serviceConfig = {
149 ExecStart = "${pkgs.ripple-data-api}/bin/api";
150 Restart = "always";
151 User = "ripple-data-api";
152 };
153 };
154
155 systemd.services.ripple-data-importer = {
156 after = [ "couchdb.service" ];
157 wantedBy = [ "multi-user.target" ];
158 path = [ pkgs.curl ];
159
160 environment = {
161 NODE_ENV = "production";
162 DEPLOYMENT_ENVS_CONFIG = pkgs.writeText "deployment.environment.json" deployment_env_config;
163 DB_CONFIG = pkgs.writeText "db.config.json" db_config;
164 LOG_FILE = "/dev/null";
165 };
166
167 serviceConfig = let
168 importMode =
169 if cfg.minLedger != null && cfg.maxLedger != null then
170 "${toString cfg.minLedger} ${toString cfg.maxLedger}"
171 else
172 cfg.importMode;
173 in {
174 ExecStart = "${pkgs.ripple-data-api}/bin/importer ${importMode} debug";
175 Restart = "always";
176 User = "ripple-data-api";
177 };
178
179 preStart = mkMerge [
180 (mkIf (cfg.couchdb.create) ''
181 HOST="http://${optionalString (cfg.couchdb.pass != "") "${cfg.couchdb.user}:${cfg.couchdb.pass}@"}${cfg.couchdb.host}:${toString cfg.couchdb.port}"
182 curl -X PUT $HOST/${cfg.couchdb.db} || true
183 '')
184 "${pkgs.ripple-data-api}/bin/update-views"
185 ];
186 };
187
188 users.extraUsers = singleton
189 { name = "ripple-data-api";
190 description = "Ripple data api user";
191 uid = config.ids.uids.ripple-data-api;
192 };
193 };
194}